Getting full path of file in COCOS2D-X on Android devices - c++

I am trying to obtain an XML file in my project but I can't seem make work right.
I am using libXML (the one that comes with cocos2d-x-2.0.4) to parse XML files.
I'm using CCFileUtils::sharedFileUtils() -> fullPathFromRelativePath( ); but the problem is, for Android versions, it will not give the full path. It works fine on iOS, though.
I then looked at the GitHub and saw something weird. It turns out that fullPathFromRelativePath( ) will only return whatever you pass onto it.
From the GitHub:
const char* CCFileUtils::fullPathFromRelativePath(const char *pszRelativePath)
{
return pszRelativePath;
}
I've looked everywhere and all I get is how to read XML files using CCFileUtils. I am already able to parse XML files. The only issue is that I can't get the full path of the XML file using fullPathFromRelativePath() in Android.
How can I get the full path of the XML file in Android?

There is nothing wrong with that function. The problem is that your xml files are inside apk, which is a zipped file, you cannot read that file directly, you should use something like
long tmpSize;
const char* xmlData = CCFileUtils::sharedFileUtils()->getFileData(YOUR_PATH_TO_FILE, "r", &tmpSize);
then you can use lib xml to handle the data you get.
but remember you cannot modify anything inside apk file. if you want to write to xml, you need to copy it to some writable path first (like sdcard or using getWritablePath()).
For the files not inside apk, you can use fopen() directly, you do not need getFileData() any more.
Hope this helps.

Related

Initialize tesseract without any external resources (languages/dictionaries)

I am currently writing a C++ program that should read hex data from JPEG images. I have to compile it into one single windows executable without any external resources (like the "tessdata" directory or config files). As I am not reading any words or sentences, I don't need any dictionaries or languages.
My problem is now that I could not find a way to initialize the API without any language files. Every example uses something like this:
tesseract::TessBaseAPI api;
if (api.Init(NULL, "eng")) {
// error handling
return -1;
}
// do stuff
I also found that I can call the init function without language argument and with OEM_TESSERACT_ONLY:
if(api.Init(NULL, NULL, tesseract::OcrEngineMode::OEM_TESSERACT_ONLY)) {
// ...
}
This should disable the language/dictionary, but NULL just defaults to "eng". It seems like tesseract still wants a language file to initialize and will disable it afterwards.
This also seems to be the case for any other solutions I found so far: I always need .traineddata files to initialize the api and can disable them afterwards or using config files.
My question is now:
Is there any way to initialize the tesseract API in C++ using just the executable and no other resource files?
No. Tesseract always needs some language (default is eng) + osd (.traineddata) files. Without language data file tesseract is useless.
Your post seems that you made several wrong assumptions (e.g. about OEM_TESSERACT_ONLY), so maybe if you describe what you try to achieve with tesseract you can get better advice.

Using Firefox website information in C++ program

I am trying to extract information from "about:plugins" website when you use Firefox web browser. I want to be able to use the contents of the website in my C++ program. Only way I know how to use content from another location is reading from a file.
What I am trying to do is read the file name and file path for each plugin from about:plugin'
Not sure if I could send this information to a file and then read it from there, but that seems like double work since if it output to file, I could just read it from there.
Needed to know how to extract information from the Firefox website in order to be used in a C++ program.
Just parse the pluginreg.dat file, you can find it in:
C:\Users\xxxxxxx\AppData\Roaming\Mozilla\Firefox\Profiles\xxxxxx.default
To obtain the AppData
char cAppData[MAX_PATH];
if(SHGetSpecialFolderPathA(NULL, cAppData, CSIDL_APPDATA, false))
{
// To obtain the profile name, parse the profiles.ini file in the folder
// ...AppData\Roaming\Mozilla\Firefox
// ...
}

Write a file in a specific path in C++

I have this code that writes successfully a file:
ofstream outfile (path);
outfile.write(buffer,size);
outfile.flush();
outfile.close();
buffer and size are ok in the rest of code.
How is possible put the file in a specific path?
Specify the full path in the constructor of the stream, this can be an absolute path or a relative path. (relative to where the program is run from)
The streams destructor closes the file for you at the end of the function where the object was created(since ofstream is a class).
Explicit closes are a good practice when you want to reuse the same file descriptor for another file. If this is not needed, you can let the destructor do it's job.
#include <fstream>
#include <string>
int main()
{
const char *path="/home/user/file.txt";
std::ofstream file(path); //open in constructor
std::string data("data to write to file");
file << data;
}//file destructor
Note you can use std::string in the file constructor in C++11 and is preferred to a const char* in most cases.
Rationale for posting another answer
I'm posting because none of the other answers cover the problem space.
The answer to your question depends on how you get the path. If you are building the path entirely within your application then see the answer from #James Kanze. However, if you are reading the path or components of the path from the environment in which your program is running (e.g. environment variable, command-line, config files etc..) then the solution is different. In order to understand why, we need to define what a path is.
Quick overview of paths
On the operating systems (that I am aware of), a path is a string which conforms to a mini-language specified by the operating-system and file-system (system for short). Paths can be supplied to IO functions on a given system in order to access some resource. For example here are some paths that you might encounter on Windows:
\file.txt
\\bob\admin$\file.txt
C:..\file.txt
\\?\C:\file.txt
.././file.txt
\\.\PhysicalDisk1\bob.txt
\\;WebDavRedirector\bob.com\xyz
C:\PROGRA~1\bob.txt
.\A:B
Solving the problem via path manipulation
Imagine the following scenario: your program supports a command line argument, --output-path=<path>, which allows users to supply a path into which your program should create output files. A solution for creating files in the specified directory would be:
Parse the user specified path based on the mini-language for the system you are operating in.
Build a new path in the mini-language which specifies the correct location to write the file using the filename and the information you parsed in step 1.
Open the file using the path generated in step 2.
An example of doing this:
On Linux, say the user has specified --output-path=/dir1/dir2
Parse this mini-language:
/dir1/dir2
--> "/" root
--> "dir1" directory under root
--> "/" path seperator
--> "dir2" directory under dir1
Then when we want to output a file in the specified directory we build a new path. For example, if we want to output a file called bob.txt, we can build the following path:
/dir1/dir2/bob.txt
--> "/" root
--> "dir1" directory under root
--> "/" path separator
--> "dir2" directory under dir1
--> "/" path seperator
--> "bob.txt" file in directory dir2
We can then use this new path to create the file.
In general it is impossible to implement this solution fully. Even if you could write code that could successfully decode all path mini-languages in existence and correctly represent the information about each system so that a new path could be built correctly - in the future your program may be built or run on new systems which have new path mini-languages that your program cannot handle. Therefore, we need to use a careful strategy for managing paths.
Path handling strategies
1. Avoid path manipulation entirely
Do not attempt to manipulate paths that are input to your program. You should pass these strings directly to api functions that can handle them correctly. This means that you need to use OS specific api's directly avoiding the C++ file IO abstractions (or you need to be absolutely sure how these abstractions are implemented on each OS). Make sure to design the interface to your program carefully to avoid a situation where you might be forced into manipulating paths. Try to implement the algorithms for your program to similarly avoid the need to manipulate paths. Document the api functions that your program uses on each OS to the user - this is because OS api functions themselves become deprecated over time so in future your program might not be compatible with all possible paths even if you are careful to avoid path manipulation.
2. Document the functions your program uses to manipulate paths
Document to the user exactly how paths will be manipulated. Then make it clear that it is the users responsibility to specify paths that will work correctly with the documented program behavior.
3. Only support a restricted set of paths
Restrict the path mini-languages your program will accept until you are confident that you can correctly manipulate the subset of paths that meet this set of restrictions. Document this to the user. Error if paths are input that do not conform.
4. Ignore the issues
Do some basic path manipulation without worrying too much. Accept that your program will exhibit undefined behavior for some paths that are input. You could document to the user that the program may or may not work when they input paths to it, and that it is the users responsibly to ensure that the program has handled the input paths correctly. However, you could also not document anything. Users will commonly expect that your program will not handle some paths correctly (many don't) and therefore will cope well even without documentation.
Closing thoughts
It is important to decide on an effective strategy for working with paths early on in the life-cycle of your program. If you have to change how paths are handled later it may be difficult to avoid a change in behaviour that might break the your program for existing users.
Try this:
ofstream outfile;
string createFile = "";
string path="/FULL_PATH";
createFile = path.as<string>() + "/" + "SAMPLE_FILENAME" + ".txt";
outfile.open(createFile.c_str());
outfile.close();
//It works like a charm.
That needs to be done when you open the file, see std::ofstream constructor or open() member.
It's not too clear what you're asking; if I understand correctly, you're
given a filename, and you want to create the file in a specific
directory. If that's the case, all that's necessary is to specify the
complet path to the constructor of ofstream. You can use string
concatenation to build up this path, but I'd strongly recommend
boost::filesystem::path. It has all of the functions to do this
portably, and a lot more; otherwise, you'll not be portable (without a
lot of effort), and even simple operations on the filename will require
considerable thought.
I was stuck on this for a while and have since figured it out. The path is based off where your executable is and varies a little. For this example assume you do a ls while in your executable directory and see:
myprogram.out Saves
Where Saves is a folder and myprogram.out is the program you are running.
In your code, if you are converting chars to a c_str() in a manner like this:
string file;
getline(cin, file, '\n');
ifstream thefile;
thefile.open( ("Saves/" + file + ".txt").c_str() );
and the user types in savefile, it would be
"Saves/savefile.txt"
which will work to get to to get to savefile.txt in your Saves folder. Notice there is no pre-slashes and you just start with the folder name.
However if you are using a string literal like
ifstream thefile;
thefile.open("./Saves/savefile.txt");
it would be like this to get to the same folder:
"./Saves/savefile.txt"
Notice you start with a ./ in front of the foldername.
If you are using linux, try execl(), with the command mv.

Read all files inside a folder including files in subfolders using C++

I want to read all files inside a given folder(path to folder) using FindFirstFile method provide in windows API. Currently I'm only succeeded in reading files inside the given folder. I could not read files inside sub folders. Can anyone help me to do this??
When you call FindFirstFile/FindNextFile, some of the "files" it returns will actually be directories.
You can check if something is a directory or not by looking at the dwFileAttributes field of the WIN32_FIND_DATA structure that gets returned to you.
If you find one that is a directory, then you can simply call your file finding function recursively to go into the subfolders.
Note: Make sure to put in a special case for the . and .. psuedo-directories, otherwise your function will recurse into itself and you'll get a stack overflow
Here's the documentation if you haven't already found it:
FindFirstFile
WIN32_FIND_DATA
possible values for dwFileAttributes (remember these are all bit flags, so you'll have to use & to check)
Alternatively, you can use boost::filesystem which will not only give you a clean API, but will also make your code portable on all supported platforms.
Take a look at this example from MSDN using CFileFind.
I've used this code to read the files in the specified directory.
CFileFind finder;
BOOL bWorking = finder.FindFile( directory );
while( bWorking )
{
bWorking = finder.FindNextFile();
}//end while

How do you include images as resources in a C++ executable?

Is it possible include images (jpegs) as resources in a win32 c++ executable? If so how?
If it's Windows only then use a custom resource. If you want something cross-platform then do what I did for a recent project - create an app that will encode the JPEG as a char* buffer in a header file and then include these headers in your main project. You will also need to store the size of the buffer as it will be sure to contain NULs.
For example, I have an app that you can pass a load of files to be encoded and for each file you get a header file that looks something like this:
#ifndef RESOURCE_SOMEFILE_JPG_HPP
#define RESOURCE_SOMEFILE_JPG_HPP
namespace resource {
const char* SOMEFILE_JPG[] =
{
...raw jpeg data...
};
const int SOMEFILE_JPG_LEN = 1234;
} // resource
#endif // RESOURCE_SOMEFILE_JPG_HPP
The app has to escape special non-printable chars in \x format, but it's pretty simple. The app uses the boost::program_options library so a list of files to encode can be stored in a config file. Each file gets its own header like similar to the above.
However, be warned - this only works for small files as some compilers have a limit on the maximum size a static char buffer can be. I'm sure there are other ways to do this but this scheme works for me (a C++ web app that stores the HTML, CSS, JavaScript and image files in this way).
Here's the MSDN documentation about resource files.
http://msdn.microsoft.com/en-us/library/aa380599(VS.85).aspx
Maybe this is what you're looking for?