2012-08-29 2 views
6

Ich versuche, eine kommagetrennte Datei namens POSDATA.GAMEDATA zu laden. Ich habe mehrere Stellen im Internet nachgeschlagen und es stellt sich heraus, dass ich ein paar Optimierungen und/oder eine andere Klasse machen muss.Datei-E/A mit COCOS2D-X

Ich versuchte mit ifstream. Es kann die Datei jedoch nicht öffnen. Xcode 4.3.2 scheint meine POSDATA.GAMEDATA Datei nicht zu finden. Ich habe auch versucht, die Datei mit ofstream zu machen, aber wenn ich open() in beiden Fällen verwende, wird die Datei nicht geöffnet.

ist mein Code so etwas wie diese:

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; 
} 

ich CCFileUtils gesehen habe, aber ich kann nicht scheinen, wie es zu benutzen.

EDIT: Ich habe versucht, die absolute Pfad (/Users/LanceGray/Documents/LanceDev/COCOS2DX/cocos2dx/TestGame/Data/POSDATA.GAMEDATA) und es funktioniert. Allerdings kann ich das nicht machen, da das Spiel in iOS-Geräten und Android verwendet werden soll, so dass der Pfad nicht immer auf jedem Gerät gleich ist. Jede Hilfe wird sehr geschätzt.

+0

Sie es auf Android oder iOS tun? Wenn Android oder Sie beide unterstützen möchten, sollten Sie besser CCFileUtils verwenden, um nicht in die ZIP-Lib zu gelangen. Auf der anderen Seite, wenn iOS, können Sie einfach fopen verwenden. Ich bin nicht sehr vertraut mit ifstream, kann nicht viel helfen. –

+0

Es soll für iOS und Android sein. Kannst du ein kleines Beispiel geben, wie man 'CCFileUtils' und' fopen' verwendet? Ich werde versuchen, in der Zwischenzeit nach ihnen zu suchen. – alxcyl

Antwort

16

Ich habe von CCFileUtils()::sharedFileUtils() -> fullPathFromRelativePath("POSDATA.GAMEDATA");

Eine ausführlichere Erklärung mit Arbeits:

  1. die Dateien hinzufügen, die Sie, indem Sie auf den Projektbaum auf der linken Seite und Right-click -> Add Files im Projekt benötigen. Was ich getan habe, war ich einen neuen Ordner namens Data auf der gleichen Ebene wie die Resources und Classes Ordnern hinzugefügt und meine POSDATA.GAMEDATA Datei dort platziert. In Xcode habe ich eine neue Gruppe hinzugefügt und diese Datei in dieser Gruppe hinzugefügt.
  2. Dann habe ich ifstream verwendet, um die Datei zu öffnen.
  3. Verwenden Sie beim Öffnen der Datei CCFileUtils()::sharedFileUtils() -> fullPathFromRelativePath(), um den absoluten Pfad der Datei abzurufen. Geben Sie den Dateinamen unter fullPathFromRelativePath() als Argument ein.
  4. Versuchen Sie es zu starten, und es sollte gut funktionieren.

Ein kleines Beispiel:

// 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; 
} 

Diese Klasse eine Datei mit dem Namen mFileContentspFileName und legen Sie es auf seinem Member-Variable geladen werden. (Beachten Sie, dass es eine public get Funktion wie vector<string> getFileContents() sollte die mFileContents zugreifen, da es private ist)

EDIT: Das obige Beispiel auf iOS funktionieren wird, aber es wird nicht auf Android-Geräten. Um dies zu beheben, verwenden Sie anstelle von ifstream stattdessen CCFileUtils::sharedUtils() -> getFileData(). In Verbindung mit CCFileUtils::sharedUtils() -> fullPathFromRelativePath() können wir unser Ziel erreichen, eine reine Textdatei zu lesen, die sowohl auf iOS als auch auf Android funktioniert.

Die FileReader Klasse würde dann so aussehen:

// 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; 
} 
+0

Was ist, wenn Sie eine riesige Datendatei auf Android haben und es sich nicht leisten können, die gesamte Datei mit getFileData() zu lesen? Es wäre schön, direkten Zugriff zu haben ... wie fseek – Cristi

2
// For versions less than v2.0.1 
// The version I am using is 0.12.0 
unsigned long fileSize = 0; 
char* pBuffer = CCFileUltils::getFileData("relative_path","r",&fileSize); 
CCLOG("Data is %s",pBuffer); 
+0

Danke für die Hilfe. Ich habe es jedoch mit 'CCFileUtils' funktioniert. – alxcyl

+0

Ich versuchte mit 'GetFileData()', aber ich bekomme eine Fehlermeldung 'Assertion fehlgeschlagen: (pszFileName! = __null && pSize! = __null && pszMode! = __null), Funktion getFileData, Datei CCFileUtils.mm, Zeile 450. ' I benutze es wie folgt: 'unsigned char * posdataLoc = CCFileUtils :: sharedFileUtils() -> getFileData (" POSDATA.GAMEDATA "," r ", 0);' – alxcyl

+0

Ich habe 'getFileData()' jetzt ausgeführt. Wenn ich es auf der Konsole aushege, zeigt es am Ende zusätzliche zufällige Zeichen. Seltsam. – alxcyl

0

Sie aus Cocos Wiki verweisen können Read/write file in cocos2d

+0

Kopieren Sie nicht den gleichen Link in mehrere Fragen und fügen Sie ihn ein. Dies ist keine Antwort, sondern ein Kommentar im besten Fall. – nikhil