Reputation: 519
I need to perform a certain file operation in C++, like this:
Please advise me a C++ solution/library which will work for both android and iOS platform.
Upvotes: 2
Views: 4558
Reputation: 6610
IF you are working for Android, you are probably gonna be writing some of your game in the Java Activity and then delegate most of the heavy work to your native C/C++ code.
So, if Steven Lu's answer isn't working out of the box, you can use Java's File class and list all filenames under any directory, and then pass that to his native file handling class and get it over with. Or, just deal with it in Java.
For iOS though, maybe this will run?
#include <dirent.h> // directory header
#include <stdio.h>
void listdir (const char *path)
{
// first off, we need to create a pointer to a directory
DIR *pdir = NULL;
pdir = opendir (path); // "." will refer to the current directory
struct dirent *pent = NULL;
if (pdir == NULL) // if pdir wasn't initialised correctly
{ // print an error message and exit the program
printf ("\nERROR! pdir could not be initialised correctly");
return; // exit the function
} // end if
while (pent = readdir (pdir)) // while there is still something in the directory to list
{
if (pent == NULL) // if pent has not been initialised correctly
{ // print an error message, and exit the program
printf ("\nERROR! pent could not be initialised correctly");
return; // exit the function
}
// otherwise, it was initialised correctly. let's print it on the console:
printf ("%s\n", pent->d_name);
}
// finally, let's close the directory
closedir (pdir);
}
/** EXAMPLE USAGE **/
int main ()
{
listdir ("C:\\");
return 0;
}
But like I said, Android will give you bigger problems as you will need to request permissions to access the SD_CARD and INTERNAL_STORAGE if you want to mess with user's files in the AndroidManifest.xml file. Mostly because most of your stuff will be just in /data/data/your.package.name folder because you will have to ship your game as an APK and not a native app (an executable binary)
So, you don't really need an android and ios library, you need a library that can run on iOS which you will later wrap around with Android's Java (Activity) :)
Upvotes: 0
Reputation: 43427
C++ gives you provisions for file interaction.
I will show you my FileReader class which employs a bit of C style file handling using C++.
// BEGIN HEADER
#include <stdio.h>
#include <exception>
#include <stdexcept>
#define DISALLOW_COPY(type) \
type(const type&); \
void operator=(const type&)
class FileReader { // RAII applies to file contents
FILE *file; // c-style open/close
DISALLOW_COPY(FileReader);
protected:
unsigned char *data; // local copy
long size;
public:
FileReader(const char *filename);
~FileReader();
unsigned long getSize();
unsigned char *getFileData();
};
// END HEADER
FileReader::FileReader(const char *filename) {
file = NULL; data = NULL;
if (!(file = fopen(filename, "rb"))) { throw std::runtime_error(std::string("File could not be opened: ")+filename); }
fseek(file,0,SEEK_END);
size = ftell(file);
rewind(file);
data = new unsigned char [size];
VERIFY(size == (long)fread(data, 1, size, file)); // debug macro (just ignore it)
fclose(file);
#ifdef DEBUG
PRINT("FileReader opening file "); printf("%s, %ld bytes.\n",filename,size);
#endif
}
FileReader::~FileReader() {
delete[] data;
}
unsigned char *FileReader::getFileData() { return data; }
unsigned long FileReader::getSize() { return size; }
I will note that you probably want to avoid using C++ to list files in the directory if you can. Why can you not simply assume whether or not certain files will be there or not be there? I've done a bit of game programming and pretty much the only times you need to worry about the filesystem are for logging purposes or for loading assets. For both of these you can pretty much just assume what their paths are.
In addition, you may want to look at the remove function for deleting files. I can't come up with any raw code in C++ for performing the task that ls
is meant for. I wouldn't use C++ to do such a task (hint: ls
is a pretty neat program).
Also take a look at stat
and opendir
(thanks Ben) which should be available on your platforms. Another point to make is that a task such as listing files in a dir are generally things you're gonna want to ask your OS kernel to do for you.
A more high-level approach mentioned by another answerer is Boost Filesystem, which is a solid choice as Boost usually is: Take a look at this directory iteration example.
From a game programming perspective I've tended to lean on stuff like Lua's os()
. For example if you have a Python program you could just do something like os.system("ls")
to get your dir contents assuming you have an ls
program available.
You could also exec
the ls
program from your C++ program.
Upvotes: 1
Reputation: 307
You could try using the Boost library, which seems to be a popular choice. It runs on iOS and Android.
See this answer on SO for more info on how to use Boost to manipulate files and directories in a cross platform way.
For example, here's some code from the Boost website to check if a particular file exists or not, checking recursively in a directory:
#include "boost/filesystem/operations.hpp"
#include "boost/filesystem/path.hpp"
#include "boost/progress.hpp"
#include <iostream>
namespace fs = boost::filesystem;
int main( int argc, char* argv[] )
{
boost::progress_timer t( std::clog );
fs::path full_path( fs::initial_path<fs::path>() );
if ( argc > 1 )
full_path = fs::system_complete( fs::path( argv[1] ) );
else
std::cout << "\nusage: simple_ls [path]" << std::endl;
unsigned long file_count = 0;
unsigned long dir_count = 0;
unsigned long other_count = 0;
unsigned long err_count = 0;
if ( !fs::exists( full_path ) )
{
std::cout << "\nNot found: " << full_path.file_string() << std::endl;
return 1;
}
if ( fs::is_directory( full_path ) )
{
std::cout << "\nIn directory: "
<< full_path.directory_string() << "\n\n";
fs::directory_iterator end_iter;
for ( fs::directory_iterator dir_itr( full_path );
dir_itr != end_iter;
++dir_itr )
{
try
{
if ( fs::is_directory( dir_itr->status() ) )
{
++dir_count;
std::cout << dir_itr->path().filename() << " [directory]\n";
}
else if ( fs::is_regular_file( dir_itr->status() ) )
{
++file_count;
std::cout << dir_itr->path().filename() << "\n";
}
else
{
++other_count;
std::cout << dir_itr->path().filename() << " [other]\n";
}
}
catch ( const std::exception & ex )
{
++err_count;
std::cout << dir_itr->path().filename() << " " << ex.what() << std::endl;
}
}
std::cout << "\n" << file_count << " files\n"
<< dir_count << " directories\n"
<< other_count << " others\n"
<< err_count << " errors\n";
}
else // must be a file
{
std::cout << "\nFound: " << full_path.file_string() << "\n";
}
return 0;
}
Upvotes: 1
Reputation: 7744
Boost filesystem is fine for you. iOS version and clang++. Boost and NDK.
Upvotes: 1