您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x判断文件是否存在for android

2013-06-04 07:36 351 查看
最近在做一款cocos2d-x的游戏,想用access去判断文件是否存在,在windows和ios平台完全ok,但是android怎么都不可以。后来发现,原来anroid的资源文件都还在apk中未解压出来,cocos2d-x针对android时这样读取文件的:

unsigned char* CCFileUtils::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize)
{
unsigned char * pData = 0;
string fullPath(pszFileName);

if ((! pszFileName) || (! pszMode))
{
return 0;
}

if (!m_obPreloadDirectory.empty()) {
do {
std::string filename = pszFileName;
size_t pos = filename.rfind("/");
if (pos != std::string::npos)
filename = filename.substr(pos + 1);
filename = m_obPreloadDirectory + filename;
FILE *fp = fopen(filename.c_str(), pszMode);
CC_BREAK_IF(!fp);

unsigned long size;
fseek(fp,0,SEEK_END);
size = ftell(fp);
fseek(fp,0,SEEK_SET);
pData = new unsigned char[size];
size = fread(pData,sizeof(unsigned char), size,fp);
fclose(fp);

if (pSize)
{
*pSize = size;
}

if (pData != NULL)
return pData;
} while (0);
}

if (pszFileName[0] != '/')
{
// read from apk
string pathWithoutDirectory = fullPath;

fullPath.insert(0, m_obDirectory.c_str());
fullPath.insert(0, "assets/");
pData =  CCFileUtils::getFileDataFromZip(s_strResourcePath.c_str(), fullPath.c_str(), pSize);

if (! pData && m_obDirectory.size() > 0)
{
// search from root
pathWithoutDirectory.insert(0, "assets/");
pData =  CCFileUtils::getFileDataFromZip(s_strResourcePath.c_str(), pathWithoutDirectory.c_str(), pSize);
}
}
else
{
do
{
// read rrom other path than user set it
FILE *fp = fopen(pszFileName, pszMode);
CC_BREAK_IF(!fp);

unsigned long size;
fseek(fp,0,SEEK_END);
size = ftell(fp);
fseek(fp,0,SEEK_SET);
pData = new unsigned char[size];
size = fread(pData,sizeof(unsigned char), size,fp);
fclose(fp);

if (pSize)
{
*pSize = size;
}
} while (0);
}

/*if (! pData && isPopupNotify())
{
std::string title = "Notification";
std::string msg = "Get data from file(";
msg.append(fullPath.c_str()).append(") failed!");
CCMessageBox(msg.c_str(), title.c_str());
}*/

return pData;
}


这个方法在cocos2d-x源码platform/android的CCFileUtils类中,我们可以看到pData = CCFileUtils::getFileDataFromZip(s_strResourcePath.c_str(), pathWithoutDirectory.c_str(), pSize)这样一段代码,其实它是直接去获取apk包里面的资源,所以你access就行不通了。

有两种方式可以解决这个问题:

1、直接判断CCFileUtils::getFileData返回值是否为NULL,不过这个方式有一个问题,当你同一个页面判断的资源很多的话,这个是很耗时的,因为它每次判断都要去解压打包,这种方式只适合判断少量文件,最好是单个文件是否存在。

2、将apk中的资源文件单独拷贝出来放到一个单独的文件夹下,比如/data/data/apkPackage/,当然拷贝也是很耗时的,通常这一步放到程序启动的时候处理,如同加载资源一样,这样做以后,可以直接判断这个文件夹里面是不是存在这个文件,对于同一个页面判断多个资源,是相当快的。

接下来讲一下第二种方式的具体作法:

在CCFileUtils类中添加两个方法:

bool CCFileUtils::isFileExist(const char* pFileName)
{
if( !pFileName ) return false;
//strFilePathName is :/data/data/ + package name
std::string filePath = m_obPreloadDirectory + pFileName;

FILE *fp = fopen(filePath.c_str(),"r");
if(fp)
{
fclose(fp);
return true;
}
return false;
}

void CCFileUtils::copyData(const char* pFileName)
{
std::string strPath = fullPathFromRelativePath(pFileName);
unsigned long len = 0;
unsigned char *data = NULL;

data = getFileData(strPath.c_str(),"r",&len);
if(data==NULL)
return;
std::string destPath = m_obPreloadDirectory;
destPath += pFileName;
FILE *fp = fopen(destPath.c_str(),"w+");
fwrite(data,sizeof(char),len,fp);
fclose(fp);
delete []data;
data = NULL;
}


isFileExist可以用来判断文件是否存在,copyData就是将apk中的资源文件拷贝到另外一个目录,当然你可以选取你需要的资源进行拷贝,因为拷贝也是一项耗时的操作。这两个方法里面都有一个私有成员m_obPreloadDirectory,这其实就是你想把文件拷贝到哪里的目录,很简单,给它一个set方法,外界设置一下这个目录就可以了,一般情况都设为/data/data/packagename。

在拷贝资源前先通过isFileExist判断一下文件是否存在,存在就不需要再拷贝了,因为刚才说过拷贝很耗时。

接下来就可以通过isFileExist方法来判断文件是否存在了。(在不断的尝试中总结经验,以帮助后面的人更快的上路,http://zhs.guohe.in/)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: