I'm trying to load up a Comma Separated file called POSDATA.GAMEDATA
. I've looked up several places on the internet and it turns out I need to do some tweaking and / or a different class.
I tried using ifstream
. However, it cannot open the file. Xcode 4.3.2 cannot seem to find my POSDATA.GAMEDATA
file. I also tried to make the file using ofstream
but when I use open()
in both cases, the file is not opened.
My code is something like this:
using namespace std;
void FileLoader::loadFile( string p_WhichFile ) {
// Local Variables
string thisLine;
// Open POSDATA.GAMEDATA
ifstream dataStream;
dataStream.open( p_WhichFile.c_str( ) );
// Check if file is opened
if ( !dataStream ) {
cerr << "[ ERROR ] Cannot load file:" << p_WhichFile.c_str( ) << endl;
exit( 1 );
}
// Get lines of strings
while ( getline( dataStream, thisLine ) ) {
fileContents.push_back( thisLine ); // fileContents is a vector< string > object
}
dataStream.close( );
cout << "[ NOTICE ] Finished reading file" << p_WhichFile << endl;
}
I've seen CCFileUtils
but I can't seem to get how to use it.
EDIT: I've tried supplying the absolute path ( /Users/LanceGray/Documents/LanceDev/COCOS2DX/cocos2dx/TestGame/Data/POSDATA.GAMEDATA
) and it worked. However, I cannot do this since the game is supposed to be used in iOS devices and Android, so the path is not always the same on each device. Any help will be grealy appreciated.
I got working by using CCFileUtils( )::sharedFileUtils( ) -> fullPathFromRelativePath( "POSDATA.GAMEDATA" );
A more detailed explanation:
Right-click -> Add Files
. What I did was I added a new folder called Data
on the same level as the Resources
and Classes
folders and placed my POSDATA.GAMEDATA
file there. In Xcode, I added a new group and added that file in that group.ifstream
to open the file.CCFileUtils( )::sharedFileUtils( ) -> fullPathFromRelativePath( )
to get the absolute path of the file. Supply the file name on the fullPathFromRelativePath( )
as argument.A small example:
// FileReader.h
#include "cocos2d.h"
using namespace std;
using namespace cocos2d;
class FileReader {
private:
vector< string > mFileContents;
public:
FileReader( string pFileName, char pMode = 'r' );
};
// FileReader.cpp
#include "FileReader.h"
#include <fstream>
#include "cocos2d.h"
using namespace cocos2d;
using namespace std;
FileReader::FileReader( string pFileName, char pMode ) {
// Create input file stream
ifstream inputStream;
string thisLine;
// Open file
inputStream.open( CCFileUtils( )::sharedFileUtils( ) -> fullPathFromRelativePath( pFileName ).c_str( ) );
// Check if it is open
if ( !inputStream.is_open( ) ) {
cerr << "[ ERROR ] Cannot open file: " << pFileName.c_str( ) << endl;
exit( 1 );
}
while ( getline( inputStream, thisLine ) ) {
// Put all lines in vector
mFileContents.push_back( thisLine );
}
inputStream.close( );
cout << "[ NOTICE ] Finished opening file: " << pFileName.c_str( ) << endl;
}
This class will load a file with the name pFileName
and place it on its member variable mFileContents
. ( Note that it should have a public get
function like vector< string > getFileContents( )
to access the mFileContents
because it is private
)
EDIT: The above sample will work on iOS, however, it won't on Android devices. So to fix this, instead of using ifstream
, use CCFileUtils::sharedUtils( ) -> getFileData( )
instead. In conjunction with CCFileUtils::sharedUtils( ) -> fullPathFromRelativePath( )
, we will be able to achieve our goal of reading a plain text file that works on both iOS and Android.
The FileReader
class would then be like this:
// FileReader.cpp
#include "FileReader.h"
#include <fstream>
#include "cocos2d.h"
using namespace cocos2d;
using namespace std;
FileReader::FileReader( string pFileName, char pMode ) {
// Initialize variables needed
unsigned long fileSize = 0;
unsigned char * fileContents = NULL;
string thisLine, result, fullPath, contents;
// Get absolute path of file
fullPath = CCFileUtils::sharedFileUtils( ) -> fullPathFromRelativePath( pFileName.c_str( ) );
// Get data of file
fileContents = CCFileUtils::sharedFileUtils( ) -> getFileData( fullPath.c_str( ) , "r", &fileSize );
contents.append( ( char * ) fileContents );
// Create a string stream so that we can use getline( ) on it
istringstream fileStringStream( contents );
// Get file contents line by line
while ( getline( fileStringStream, thisLine ) ) {
// Put all lines in vector
mFileContents.push_back( thisLine );
}
// After this, mFileContents will have an extra entry and will have the value '\x04'.
// We should remove this by popping it out the vector.
mFileContents.pop_back( );
// Delete buffer created by fileContents. This part is required.
if ( fileContents ) {
delete[ ] fileContents;
fileContents = NULL;
}
// For testing purposes
cout << "[ NOTICE ] Finished opening file: " << pFileName.c_str( ) << endl;
}