最近在做一款cocos2d-x的游戲,想用access去判斷文件是否存在,在windows和ios平臺(tái)完全ok,但是android怎么都不可以。后來(lái)發(fā)現(xiàn),原來(lái)anroid的資源文件都還在apk中未解壓出來(lái),cocos2d-x針對(duì)android時(shí)這樣讀取文件的:
1 unsigned char* CCFileUtils::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize) 2 { 3 unsigned char * pData = 0; 4 string fullPath(pszFileName); 5 6 if ((! pszFileName) || (! pszMode)) 7 { 8 return 0; 9 } 10 11 if (!m_obPreloadDirectory.empty()) { 12 do { 13 std::string filename = pszFileName; 14 size_t pos = filename.rfind("/"); 15 if (pos != std::string::npos) 16 filename = filename.substr(pos + 1); 17 filename = m_obPreloadDirectory + filename; 18 FILE *fp = fopen(filename.c_str(), pszMode); 19 CC_BREAK_IF(!fp); 20 21 unsigned long size; 22 fseek(fp,0,SEEK_END); 23 size = ftell(fp); 24 fseek(fp,0,SEEK_SET); 25 pData = new unsigned char[size]; 26 size = fread(pData,sizeof(unsigned char), size,fp); 27 fclose(fp); 28 29 if (pSize) 30 { 31 *pSize = size; 32 } 33 34 if (pData != NULL) 35 return pData; 36 } while (0); 37 } 38 39 if (pszFileName[0] != '/') 40 { 41 // read from apk 42 string pathWithoutDirectory = fullPath; 43 44 fullPath.insert(0, m_obDirectory.c_str()); 45 fullPath.insert(0, "assets/"); 46 pData = CCFileUtils::getFileDataFromZip(s_strResourcePath.c_str(), fullPath.c_str(), pSize); 47 48 if (! pData && m_obDirectory.size() > 0) 49 { 50 // search from root 51 pathWithoutDirectory.insert(0, "assets/"); 52 pData = CCFileUtils::getFileDataFromZip(s_strResourcePath.c_str(), pathWithoutDirectory.c_str(), pSize); 53 } 54 } 55 else 56 { 57 do 58 { 59 // read rrom other path than user set it 60 FILE *fp = fopen(pszFileName, pszMode); 61 CC_BREAK_IF(!fp); 62 63 unsigned long size; 64 fseek(fp,0,SEEK_END); 65 size = ftell(fp); 66 fseek(fp,0,SEEK_SET); 67 pData = new unsigned char[size]; 68 size = fread(pData,sizeof(unsigned char), size,fp); 69 fclose(fp); 70 71 if (pSize) 72 { 73 *pSize = size; 74 } 75 } while (0); 76 } 77 78 /*if (! pData && isPopupNotify()) 79 { 80 std::string title = "Notification"; 81 std::string msg = "Get data from file("; 82 msg.append(fullPath.c_str()).append(") failed!"); 83 CCMessageBox(msg.c_str(), title.c_str()); 84 }*/ 85 86 return pData; 87 }
這個(gè)方法在cocos2d-x源碼platform/android的CCFileUtils類中,我們可以看到pData = CCFileUtils::getFileDataFromZip(s_strResourcePath.c_str(), pathWithoutDirectory.c_str(), pSize)這樣一段代碼,其實(shí)它是直接去獲取apk包里面的資源,所以你access就行不通了。
有兩種方式可以解決這個(gè)問(wèn)題:
1、直接判斷CCFileUtils::getFileData返回值是否為NULL,不過(guò)這個(gè)方式有一個(gè)問(wèn)題,當(dāng)你同一個(gè)頁(yè)面判斷的資源很多的話,這個(gè)是很耗時(shí)的,因?yàn)樗看闻袛喽家ソ鈮捍虬,這種方式只適合判斷少量文件,最好是單個(gè)文件是否存在。
2、將apk中的資源文件單獨(dú)拷貝出來(lái)放到一個(gè)單獨(dú)的文件夾下,比如/data/data/apkPackage/,當(dāng)然拷貝也是很耗時(shí)的,通常這一步放到程序啟動(dòng)的時(shí)候處理,如同加載資源一樣,這樣做以后,可以直接判斷這個(gè)文件夾里面是不是存在這個(gè)文件,對(duì)于同一個(gè)頁(yè)面判斷多個(gè)資源,是相當(dāng)快的。
接下來(lái)講一下第二種方式的具體作法:
在CCFileUtils類中添加兩個(gè)方法:
1 bool CCFileUtils::isFileExist(const char* pFileName) 2 { 3 if( !pFileName ) return false; 4 //strFilePathName is :/data/data/ + package name 5 std::string filePath = m_obPreloadDirectory + pFileName; 6 7 FILE *fp = fopen(filePath.c_str(),"r"); 8 if(fp) 9 { 10 fclose(fp); 11 return true; 12 } 13 return false; 14 } 15 16 void CCFileUtils::copyData(const char* pFileName) 17 { 18 std::string strPath = fullPathFromRelativePath(pFileName); 19 unsigned long len = 0; 20 unsigned char *data = NULL; 21 22 data = getFileData(strPath.c_str(),"r",&len); 23 if(data==NULL) 24 return; 25 std::string destPath = m_obPreloadDirectory; 26 destPath += pFileName; 27 FILE *fp = fopen(destPath.c_str(),"w+"); 28 fwrite(data,sizeof(char),len,fp); 29 fclose(fp); 30 delete []data; 31 data = NULL; 32 }
isFileExist可以用來(lái)判斷文件是否存在,copyData就是將apk中的資源文件拷貝到另外一個(gè)目錄,當(dāng)然你可以選取你需要的資源進(jìn)行拷貝,因?yàn)榭截愐彩且豁?xiàng)耗時(shí)的操作。這兩個(gè)方法里面都有一個(gè)私有成員m_obPreloadDirectory,這其實(shí)就是你想把文件拷貝到哪里的目錄,很簡(jiǎn)單,給它一個(gè)set方法,外界設(shè)置一下這個(gè)目錄就可以了,一般情況都設(shè)為/data/data/packagename。
在拷貝資源前先通過(guò)isFileExist判斷一下文件是否存在,存在就不需要再拷貝了,因?yàn)閯偛耪f(shuō)過(guò)拷貝很耗時(shí)。
接下來(lái)就可以通過(guò)isFileExist方法來(lái)判斷文件是否存在了。(在不斷的嘗試中總結(jié)經(jīng)驗(yàn),以幫助后面的人更快的上路)