2012-08-29 8 views
6

Próbuję załadować plik rozdzielany przecinkami o nazwie POSDATA.GAMEDATA. Szukałem kilku miejsc w Internecie i okazało się, że muszę zrobić kilka poprawek i/lub inną klasę.Plik we/wy używający COCOS2D-X

Próbowałem użyć ifstream. Jednak nie można otworzyć pliku. Xcode 4.3.2 nie może znaleźć mojego pliku POSDATA.GAMEDATA. Próbowałem również zrobić plik przy użyciu ofstream, ale kiedy używam open() w obu przypadkach, plik nie jest otwierany.

Mój kod jest coś takiego:

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

Widziałem CCFileUtils ale nie wydaje się uzyskać jak go używać.

EDIT: Próbowałem dostarczanie absolutnej ścieżki (/Users/LanceGray/Documents/LanceDev/COCOS2DX/cocos2dx/TestGame/Data/POSDATA.GAMEDATA) i zadziałało. Nie mogę tego zrobić, ponieważ gra ma być używana na urządzeniach iOS i Androidzie, więc ścieżka nie zawsze jest taka sama na każdym urządzeniu. Każda pomoc zostanie doceniona.

+0

robisz to na Androida lub iOS? jeśli Android lub masz zamiar obsługiwać oba, myślę, że lepiej użyć CCFileUtils, aby uniknąć dostępu do lib zip. Z drugiej strony, jeśli iOS, możesz po prostu użyć fopen. Nie znam zbytnio Ifstream, nie mogę pomóc. –

+0

To powinno być zarówno dla systemu iOS, jak i Androida. Czy możesz podać mały przykład użycia 'CCFileUtils' i' fopen'? W międzyczasie spróbuję ich szukać. – alxcyl

Odpowiedz

16

Mam pracę za pomocą CCFileUtils()::sharedFileUtils() -> fullPathFromRelativePath("POSDATA.GAMEDATA");

bardziej szczegółowe wyjaśnienie:

  1. Dodaj pliki, które są potrzebne w projekcie, przechodząc do drzewa projektu po lewej i Right-click -> Add Files. To, co zrobiłem, dodałem nowy folder o nazwie Data na tym samym poziomie co foldery Resources i Classes i umieściłem tam plik POSDATA.GAMEDATA. W Xcode dodałem nową grupę i dodałem ten plik do tej grupy.
  2. Następnie użyłem ifstream, aby otworzyć plik.
  3. Podczas otwierania pliku należy użyć CCFileUtils()::sharedFileUtils() -> fullPathFromRelativePath(), aby uzyskać bezwzględną ścieżkę do pliku. Podaj nazwę pliku w argumencie fullPathFromRelativePath() jako.
  4. Spróbuj uruchomić i powinno działać poprawnie.

Mały przykład:

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

Ta klasa będzie załadować plik o nazwie pFileName i umieścić go na swoim członkiem zmiennej mFileContents. (Należy pamiętać, że powinien on mieć public get funkcję jak vector<string> getFileContents() dostępu do mFileContents ponieważ jest private)

EDIT: Powyższy przykład działa na iOS, jednak nie będzie na urządzeniach z systemem Android. Aby to naprawić, zamiast używać ifstream, użyj zamiast tego CCFileUtils::sharedUtils() -> getFileData(). W połączeniu z CCFileUtils::sharedUtils() -> fullPathFromRelativePath(), będziemy mogli osiągnąć nasz cel, jakim jest czytanie zwykłego pliku tekstowego, który działa zarówno na iOS, jak i na Androida.

Klasa FileReader będzie wówczas tak:

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

Co zrobić, jeśli masz ogromny plik danych na Androida i nie możesz sobie pozwolić na odczytanie całego pliku za pomocą funkcji getFileData()? Byłoby miło mieć większy bezpośredni dostęp ... jak 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

Dzięki za pomoc. Mam to działa przy użyciu 'CCFileUtils', choć. – alxcyl

+0

Próbowałem używać 'getFileData()', ale pojawia się komunikat "Assertion failed: (pszFileName! = __null && pSize! = __null && pszMode! = __null), funkcja getFileData, plik CCFileUtils.mm, wiersz 450. ' I użył tego w następujący sposób: 'unsigned char * posdataLoc = CCFileUtils :: sharedFileUtils() -> getFileData (" POSDATA.GAMEDATA "," r ", 0);' – alxcyl

+0

Mam 'getFileData()' działający teraz. Kiedy "cout" to na konsoli, pokazuje dodatkowe losowe znaki na końcu. Dziwne. – alxcyl

0

Można odwołać się od wiki Cocos męska Read/write file in cocos2d

+0

Nie kopiuj i nie wklejaj tego samego linku w wielu pytaniach. To nie jest odpowiedź, ale w najlepszym razie komentarz. – nikhil

Powiązane problemy