Opening files on Android using Cocos2d-x api - c++

I am having difficulty opening a file with cocos2d-x FileUtils in an android project. I am using Cocos2d-x v2.2.3 and the create_project.py to set up my project structure. There is a folder called Resources that contains some HelloWorld png's. I would like to add other files to this folder and then perform read operations with standard file stream operations. However, opening the file fails when running on the Android emulator. I have tried using CCFileUtils::sharedFileUtils()->getWritablePath() and then appending the name of the file. What is the correct way to use Cocos2d-x to open files on android?

The folder Resources contains files for which the app has only a read access.
To get the correct path to these files use:
string yourFilename = "hello.txt"; // only (relative path+) filename here, no absolute path!
string fullPath = CCFileUtils::sharedFileUtils()->fullPathForFilename(yourFilename.c_str());
Open the file using fullPath!
The routine searches in a number of paths which can be extended.
See description of CCFileUtils::fullPathForFilename()
To define the search paths and the search order write something like:
vector<string> searchPaths;
searchPaths.push_back("1st_path");
searchPaths.push_back("2nd_path");
searchPaths.push_back("3rd_path");
CCFileUtils::sharedFileUtils()->setSearchResolutionsOrder(searchPaths);
For Android apps the Resource folder is already part of the search paths, so no need to add it here.
To see the different paths try:
CCLOG ("full path: %s", fullPath.c_str());
CCLOG ("writable path: %s", CCFileUtils::sharedFileUtils()->getWritablePath().c_str());

Related

How to read a file on Hololens with C++

I am trying to read a file in a test/debug UWP application that is being deployed to Hololens. I can put the file on the device with the device portal, but am unable to find the correct path to open the file.
I am using the MSFT BasicXrApp_uwp example as a basis, and have included FileUtility which has a FindFileInAppFolder function. This is consistently failing to find the file, with the error:
"The file should be embeded in app folder in debug build.",
after letting me know the app folder is:
C:\Data\Users\DefaultAccount\AppData\Local\DevelopmentFiles\364f83f4-6e13-42e4-8253-71dd3040951cVS.Debug_ARM.mikeh\
The part 364f83f4-6e13-42e4-8253-71dd3040951cVS is recognisable in the device portal as the User Folders/LocalAppData folder, but the Debug_ARM.mikeh part is not visible on the portal.
I am using C++ and trying to do the file reading in a static, non uwp library if possible (pointing that out so I don't get suggestions to use UWP async stuff, if that is possible).
So, how do I embed my file in the app folder, or how do I place the file so I can read it?
This is because the folder path which FindFileInAppFolder method returns is the InstalledLocation of the current package, but what you checked in the device portal is LocalFolder/LocalCacheFolder, for more information about what different between them please see: File access permissions.
how do I embed my file in the app folder, or how do I place the file so I can read it?
You can place your file in the LocalState folder by Device Portal and get this folder path through ApplicationData.LocalFolder Property, the path should be like: C:\Data\Users\DefaultAccount\AppData\Local\Packages\364f83f4-6e13-42e4-8253-71dd3040951c\LocalState. For how to access the files via C++ you can use for example File access sample
I'm using an answer here as there's more room than a comment.
I found a few extra things useful. I added in the cppWinRT nuget package to my application.
I did need to use the "async stuff", for example:
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage;
StorageFolder storageFolder= KnownFolders::GetFolderForUserAsync(nullptr, KnownFolderId::PicturesLibrary).get();
This let me find a file I'd uploaded ot the Pictures Library. But I couldn't open it after passing the path to my existing library:
const auto sampleFile = storageFolder.GetFileAsync(fileName).get();
std::wstring path = sampleFile.Path();
MyLibraryCall(to_string(path));
MyLibraryCall would try and open an ifstream, and even using std::ifstream::in would fail.
So I copied the file to the temp directory, where I could open it and process it.
This is pretty hacky but it did what I needed, which is let me load an .obj file that was rejected by the 3D parts viewer.
The loop over all filenames is because storageFolder.GetFileAsync(fileName).get() throws an exception if it fails, which for me I could not catch properly.
StorageFolder tempFolder = Windows::Storage::ApplicationData::Current().TemporaryFolder();
std::wstring path;
auto files = tempFolder.GetFilesAsync().get();
for (auto file : files)
{
if (file.Name() == fileName) {
path = file.Path();
break;
}
}
if (!path.size()) {
// hasn't been copied into temp
StorageFile movedFile = sampleFile.CopyAsync(tempFolder).get();
path = movedFile.Path();
}
MyLibraryCall(to_string(path));
Anyway- not the greatest but that will hopefully help someone else looking for a quick and dirty way to process a file on a hololens/UWP app.

Qt, read in a local text file

I have tried to use QFile to open a text file:
I tried
QFile file("serial_deviceIP.txt");
but the file.open() returns false.
However, if I switched to a global address like:
QFile file("C:/Users/shupeng/Documents/qgroundcontrol_peidong_mod/serial_deviceIP.txt");
it works. Why? How can I solve this?
In the first instance, the path to the file cannot be found.
QFile file("serial_deviceIP.txt");
This specifies the file with a relative path, and will only work if serial_deviceIP.txt is in the current working directory, which is likely to be the directory that contains the executable of your program.
QFile file("C:/Users/shupeng/Documents/qgroundcontrol_peidong_mod/serial_deviceIP.txt");
This is referencing an absolute file path, so the file will be found
You can also use Qt's Resource System to bundle the files with your application.
Create a .qrc file in your project and add any file you wish to use/load in your application to it.
Then you can load your file as:
QFile file( ":myfiles/serial_deviceIP.txt" );
See QT Resource System for more information.
What happens is that when we are developing our code we usually keep our project source dir on mind as the reference so we don't give an absolute path, but after building the current directory will change and it will be the build directory, so our application won't find the files without a absolute path.
A possible solution is to add a Resources in our project including our project directory. So just add the following line in the project_file.pro:
RESOURCES += ./
and then use the character : before the file's name when you go to read it, like it:
QFile foo(":bar.txt")
That just work for read it but not for write. So to write is necessary specify an absolute path.

Opening a file in the current directory

I'm trying to load files, and previously I was using hardcoded file locations, (like "c:\location\file.txt") but now that a few friends are also using the file, I'd like to allow them to put the executable wherever they want.
my current code looks like:
ifstream myfile;
myfile.open("c:\\client\\settings.cfg");
I'm trying to change it so that the user puts their executable into whatever folder they want, and then they create a folder and put their settings file into it and the exe will load that with their settings.
ifstream myfile;
myfile.open("\\settings\\settings.cfg");
I have some basic error handling in place, and now the program always errors out saying that it can't find the file.
The file structure looks like this:
[ART]
asset.png
[SETTINGS]
settings.cfg
client.exe
This seems like a really simple thing to do, but I can't find any way to do it. Every example and tutorial about reading and writing to files deals only with files in the executable's directory, or hardcoded into c:\folder...
Could anyone point me to how I do this?
The search path for most systems starts with the current working directory and then to a PATH environment variable. So, all you need to do is specify the file/folder without the absolute path markings and it will use the path relative to the working directory:
ifstream myfile;
myfile.open("settings\\settings.cfg");
// ^^ Note the lack of \\ to start the file path
Paths beginning with \ are always relative to the current drive's root directory. If the current drive is C:, then \settings\settings.cfg means C:\settings\settings.cfg.
Note that you can use / in order to avoid escaping everything. So you can use: settings/settings.cfg. This will be relative to the user's current directory. Note however, that this doesn't necessarily correspond to the directory where the executable resides. If you need the directory of the executable, then you need to use a Windows API function to get it:
#include <Windows.h>
// ...
HMODULE module = GetModuleHandleW(NULL);
WCHAR path[MAX_PATH];
GetModuleFileNameW(module, path, MAX_PATH);
Now if you want to open settings/settings.cfg relative to the directory of the executable, create a path that starts with path and append /settings/settings.cfg to it.

Get list of files in application directory

I am developing a C++ application for win32 console
I need to get list of files in my application directory
(for example if my application had been started in C:\arash\app\ I need list of files in this folder)
I searched and find FindFirstFile function in windows.h header , But this function need a directory path .
Can I use this function for getting list of files in my application running directory?
Thanks
Use GetModuleFileName() with a NULL module handle to get the path and filename of the .exe file. You can then strip off the filename portion, and use the remaining path as needed.
The current working directory is '.'.
As noted in comments, this isn't necessarily the directory you want.

Relative path problem for a deployed win32 application

I have written a c++ program and deployed it in say c:\my_app, and my executable's path is c:\my_app\my_app.exe. Say, my_app needs many files such as the_file.txt, which is located in c:\my_app\the_file.txt.
In my executable, I open the txt file as, xx.open("the_file.txt");
Moreover, I have associated my program with let's say .myp extension.
When I'm on Desktop, and want to open a file named example.myp, my program can not see the_file.txt. Because, it (somehow) assumes that it's currently working on Desktop.
Is there any easy way to handle this problem by changing shell command for open in HKEY_CLASSES_ROOT? The naive solution would be to change all file open operations with something like %my_app_location/the_file.txt". I don't want to do that.
Always use a full path name to open a file. In other words, don't open "foo.txt", open "c:\bar\foo.txt". To find the install directory of your EXE use GetModuleFileName(), passing NULL for the module handle.
These days you shouldn't add files to c:\my_app....
Instead use the ProgramData Folder and full paths.
Use SHGetSpecialFolderPathA with CSIDL_COMMON_APPDATA to get the ProgramData folder and the create your program directory and add your files.
You should set current directory for your app's folder with SetCurrentDirectory function. After that you can open file by name without full path