【问题标题】:File I/O using COCOS2D-X使用 COCOS2D-X 进行文件 I/O
【发布时间】:2012-08-23 16:19:37
【问题描述】:

我正在尝试加载名为POSDATA.GAMEDATA 的逗号分隔文件。我在互联网上查找了几个地方,结果发现我需要做一些调整和/或不同的课程。

我尝试使用ifstream。但是,它无法打开该文件。 Xcode 4.3.2 似乎找不到我的POSDATA.GAMEDATA 文件。我也尝试使用ofstream 创建文件,但是当我在这两种情况下使用open() 时,文件都没有打开。

我的代码是这样的:

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

我见过CCFileUtils,但我似乎不知道如何使用它。

编辑:我尝试过提供绝对路径(/Users/LanceGray/Documents/LanceDev/COCOS2DX/cocos2dx/TestGame/Data/POSDATA.GAMEDATA)并且它有效。但是,我不能这样做,因为该游戏应该在 iOS 设备和 Android 设备中使用,因此每个设备上的路径并不总是相同的。任何帮助将不胜感激。

【问题讨论】:

  • 您是在 Android 还是 iOS 上进行操作?如果 android 或者您打算同时支持两者,我想您最好使用 CCFileUtils 来避免进入 zip lib。另一方面,如果是 iOS,你可以只使用 fopen。我对 ifstream 不是很熟悉,帮不上什么忙。
  • 它应该适用于 iOS 和 Android。你能举一个小例子来说明如何使用CCFileUtilsfopen吗?在此期间,我会尝试寻找它们。

标签: c++ xcode cocos2d-x


【解决方案1】:

我使用CCFileUtils( )::sharedFileUtils( ) -&gt; fullPathFromRelativePath( "POSDATA.GAMEDATA" );开始工作

更详细的解释:

  1. 通过转到左侧的项目树和Right-click -&gt; Add Files,在项目中添加您需要的文件。我所做的是在与ResourcesClasses 文件夹相同的级别上添加了一个名为Data 的新文件夹,并将我的POSDATA.GAMEDATA 文件放在那里。在 Xcode 中,我添加了一个新组并将该文件添加到该组中。
  2. 然后我用ifstream打开了文件。
  3. 打开文件时,使用CCFileUtils( )::sharedFileUtils( ) -&gt; fullPathFromRelativePath( )获取文件的绝对路径。提供 fullPathFromRelativePath( ) 上的文件名作为参数。
  4. 尝试运行它,它应该可以正常工作。

一个小例子:

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

该类将加载一个名为pFileName 的文件并将其放在其成员变量mFileContents 中。 (注意它应该有一个public get 函数,比如vector&lt; string &gt; getFileContents( ) 来访问mFileContents,因为它是private

编辑:上述示例适用于 iOS,但不适用于 Android 设备。所以要解决这个问题,不要使用ifstream,而是使用CCFileUtils::sharedUtils( ) -&gt; getFileData( )。结合CCFileUtils::sharedUtils( ) -&gt; fullPathFromRelativePath( ),我们将能够实现读取适用于 iOS 和 Android 的纯文本文件的目标。

FileReader 类将是这样的:

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

【讨论】:

  • 如果你在 android 上有一个巨大的数据文件并且无法使用 getFileData() 读取整个文件怎么办?有更多的直接访问权限会很好......比如 fseek
【解决方案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);

【讨论】:

  • 感谢您的帮助。不过,我已经使用CCFileUtils 让它工作了。
  • 我尝试使用getFileData(),但出现错误提示Assertion failed: (pszFileName != __null &amp;&amp; pSize != __null &amp;&amp; pszMode != __null), function getFileData, file CCFileUtils.mm, line 450. 我是这样使用的:unsigned char * posdataLoc = CCFileUtils::sharedFileUtils() -&gt; getFileData( "POSDATA.GAMEDATA", "r", 0 );
  • 我得到了getFileData( ) 的工作。当我在控制台上cout 它时,它最后会显示额外的随机字符。很奇怪。
【解决方案3】:

可以参考 Cocos 的 wiki Read/write file in cocos2d

【讨论】:

  • 不要在多个问题中复制粘贴同一个链接。这不是答案,充其量只是评论。
猜你喜欢
  • 1970-01-01
  • 2012-05-26
  • 1970-01-01
  • 2015-02-13
  • 1970-01-01
  • 1970-01-01
  • 2016-02-09
  • 2023-04-10
  • 1970-01-01
相关资源
最近更新 更多