Add FileUtils::getSuitableFOpen

win32 fopen only ansi encoding.
if filePath contains utf8 characters fopen fail.
AudioCache FileFormat::OGG bag, can't open file, if filePath contains
utf8.

Need make all filename for fopen correct encoding.
Only Win32 FileUtils::getSuitableFOpen return
StringUtf8ToAnsi(filename),
other platform return filename

all fopen use FileUtils::getSuitableFOpen
This commit is contained in:
Vladimir Perminov 2015-04-19 14:00:27 +03:00
parent 425b2b62e1
commit 694b9adc1e
13 changed files with 130 additions and 22 deletions

View File

@ -29,6 +29,7 @@
#include <thread>
#include <algorithm>
#include "base/CCConsole.h"
#include "platform/CCFileUtils.h"
#include "mpg123.h"
#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"
@ -96,8 +97,9 @@ void AudioCache::readDataTask()
case FileFormat::OGG:
{
vf = new OggVorbis_File;
if (ov_fopen(_fileFullPath.c_str(), vf)){
log("Input does not appear to be an Ogg bitstream.\n");
int openCode;
if (openCode = ov_fopen(FileUtils::getInstance()->getSuitableFOpen(_fileFullPath).c_str(), vf)){
log("Input does not appear to be an Ogg bitstream: %s. Code: 0x%x\n", _fileFullPath.c_str(), openCode);
goto ExitThread;
}

View File

@ -27,6 +27,7 @@
#include "AudioPlayer.h"
#include "AudioCache.h"
#include "base/CCConsole.h"
#include "platform/CCFileUtils.h"
#include "mpg123.h"
#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"
@ -162,8 +163,9 @@ void AudioPlayer::rotateBufferThread(int offsetFrame)
case AudioCache::FileFormat::OGG:
{
vorbisFile = new OggVorbis_File;
if (ov_fopen(_audioCache->_fileFullPath.c_str(), vorbisFile)){
log("Input does not appear to be an Ogg bitstream.\n");
int openCode;
if (openCode = ov_fopen(FileUtils::getInstance()->getSuitableFOpen(_audioCache->_fileFullPath).c_str(), vorbisFile)){
log("Input does not appear to be an Ogg bitstream: %s. Code: 0x%x\n", _audioCache->_fileFullPath.c_str(), openCode);
goto ExitBufferThread;
}
if (offsetFrame != 0) {

View File

@ -330,7 +330,6 @@ Console::Console()
{
_commands[commands[i].name] = commands[i];
}
_writablePath = FileUtils::getInstance()->getWritablePath();
}
Console::~Console()
@ -870,9 +869,10 @@ void Console::commandUpload(int fd)
}
*ptr = 0;
std::string filepath = _writablePath + std::string(buf);
static std::string writablePath = FileUtils::getInstance()->getWritablePath();
std::string filepath = writablePath + std::string(buf);
FILE* fp = fopen(filepath.c_str(), "wb");
FILE* fp = fopen(FileUtils::getInstance()->getSuitableFOpen(filepath).c_str(), "wb");
if(!fp)
{
const char err[] = "can't create file!\n";

View File

@ -140,8 +140,6 @@ protected:
bool _running;
bool _endThread;
std::string _writablePath;
std::map<std::string, Command> _commands;
// strings generated by cocos2d sent to the remote console

View File

@ -132,7 +132,7 @@ static void setValueForKey(const char* pKey, const char* pValue)
// save file and free doc
if (doc)
{
doc->SaveFile(UserDefault::getInstance()->getXMLFilePath().c_str());
doc->SaveFile(FileUtils::getInstance()->getSuitableFOpen(UserDefault::getInstance()->getXMLFilePath()).c_str());
delete doc;
}
}
@ -484,7 +484,7 @@ bool UserDefault::createXMLFile()
return false;
}
pDoc->LinkEndChild(pRootEle);
bRet = tinyxml2::XML_SUCCESS == pDoc->SaveFile(_filePath.c_str());
bRet = tinyxml2::XML_SUCCESS == pDoc->SaveFile(FileUtils::getInstance()->getSuitableFOpen(_filePath).c_str());
if(pDoc)
{

View File

@ -403,7 +403,7 @@ bool FileUtils::writeToFile(ValueMap& dict, const std::string &fullPath)
}
rootEle->LinkEndChild(innerDict);
bool ret = tinyxml2::XML_SUCCESS == doc->SaveFile(fullPath.c_str());
bool ret = tinyxml2::XML_SUCCESS == doc->SaveFile(getSuitableFOpen(fullPath).c_str());
delete doc;
return ret;
@ -566,7 +566,7 @@ static Data getData(const std::string& filename, bool forString)
{
// Read the file from hardware
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(filename);
FILE *fp = fopen(fullPath.c_str(), mode);
FILE *fp = fopen(FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str(), mode);
CC_BREAK_IF(!fp);
fseek(fp,0,SEEK_END);
size = ftell(fp);
@ -629,7 +629,7 @@ unsigned char* FileUtils::getFileData(const std::string& filename, const char* m
{
// read the file from hardware
const std::string fullPath = fullPathForFilename(filename);
FILE *fp = fopen(fullPath.c_str(), mode);
FILE *fp = fopen(getSuitableFOpen(fullPath).c_str(), mode);
CC_BREAK_IF(!fp);
fseek(fp,0,SEEK_END);
@ -1364,5 +1364,10 @@ bool FileUtils::isPopupNotify() const
return s_popupNotify;
}
std::string FileUtils::getSuitableFOpen(const std::string& filenameUtf8) const
{
return filenameUtf8;
}
NS_CC_END

View File

@ -330,6 +330,16 @@ public:
// This method is used internally.
virtual bool writeToFile(ValueMap& dict, const std::string& fullPath);
/**
* Windows fopen can't support UTF-8 filename
* Need convert all parameters fopen and other 3rd-party libs
* CC_PLATFORM_WP8 and CC_PLATFORM_WINRT the same needs?
*
* @param filename std::string name file for convertation from utf-8
* @return std::string ansi filename in current locale
*/
virtual std::string getSuitableFOpen(const std::string& filenameUtf8) const;
// Converts the contents of a file to a ValueVector.
// This method is used internally.
virtual ValueVector getValueVectorFromFile(const std::string& filename);

View File

@ -2232,7 +2232,7 @@ bool Image::saveImageToPNG(const std::string& filePath, bool isToRGB)
png_colorp palette;
png_bytep *row_pointers;
fp = fopen(filePath.c_str(), "wb");
fp = fopen(FileUtils::getInstance()->getSuitableFOpen(filePath).c_str(), "wb");
CC_BREAK_IF(nullptr == fp);
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
@ -2388,7 +2388,7 @@ bool Image::saveImageToJPG(const std::string& filePath)
/* Now we can initialize the JPEG compression object. */
jpeg_create_compress(&cinfo);
CC_BREAK_IF((outfile = fopen(filePath.c_str(), "wb")) == nullptr);
CC_BREAK_IF((outfile = fopen(FileUtils::getInstance()->getSuitableFOpen(filePath).c_str(), "wb")) == nullptr);
jpeg_stdio_dest(&cinfo, outfile);

View File

@ -56,6 +56,81 @@ static inline std::string convertPathFormatToUnixStyle(const std::string& path)
return ret;
}
static std::wstring StringUtf8ToWideChar(const std::string& strUtf8)
{
std::wstring ret;
if (!strUtf8.empty())
{
int nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, nullptr, 0);
if (nNum)
{
WCHAR* wideCharString = new WCHAR[nNum + 1];
wideCharString[0] = 0;
nNum = MultiByteToWideChar(CP_UTF8, 0, strUtf8.c_str(), -1, wideCharString, nNum + 1);
ret = wideCharString;
delete[] wideCharString;
}
else
{
CCLOG("Wrong convert to WideChar code:0x%x", GetLastError());
}
}
return ret;
}
static std::string StringWideCharToUtf8(const std::wstring& strWideChar)
{
std::string ret;
if (!strWideChar.empty())
{
int nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE);
if (nNum)
{
char* utf8String = new char[nNum + 1];
utf8String[0] = 0;
nNum = WideCharToMultiByte(CP_UTF8, 0, strWideChar.c_str(), -1, utf8String, nNum + 1, nullptr, FALSE);
ret = utf8String;
delete[] utf8String;
}
else
{
CCLOG("Wrong convert to Utf8 code:0x%x", GetLastError());
}
}
return ret;
}
static std::string StringUtf8ToAnsi(const std::string& strUtf8)
{
std::string ret;
if (!strUtf8.empty())
{
std::wstring strWideChar = NS_CC::StringUtf8ToWideChar(strUtf8);
int nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, nullptr, 0, nullptr, FALSE);
if (nNum)
{
char* ansiString = new char[nNum + 1];
ansiString[0] = 0;
nNum = WideCharToMultiByte(CP_ACP, 0, strWideChar.c_str(), -1, ansiString, nNum + 1, nullptr, FALSE);
ret = ansiString;
delete[] ansiString;
}
else
{
CCLOG("Wrong convert to Ansi code:0x%x", GetLastError());
}
}
return ret;
}
static void _checkPath()
{
if (0 == s_resourcePath.length())
@ -334,6 +409,11 @@ string FileUtilsWin32::getWritablePath() const
return ret;
}
std::string FileUtilsWin32::getSuitableFOpen(const std::string& filenameUtf8) const
{
return StringUtf8ToAnsi(filenameUtf8);
}
NS_CC_END
#endif // CC_TARGET_PLATFORM == CC_PLATFORM_WIN32

View File

@ -54,6 +54,17 @@ public:
protected:
virtual bool isFileExistInternal(const std::string& strFilePath) const;
/**
* Windows fopen can't support UTF-8 filename
* Need convert all parameters fopen and other 3rd-party libs
* CC_PLATFORM_WP8 and CC_PLATFORM_WINRT the same needs?
*
* @param filename std::string name file for convertation from utf-8
* @return std::string ansi filename in current locale
*/
virtual std::string getSuitableFOpen(const std::string& filenameUtf8) const override;
/**
* Gets resource file data

View File

@ -359,7 +359,7 @@ bool AssetsManager::uncompress()
{
const string dir=_storagePath+fileNameStr.substr(0,index);
FILE *out = fopen(dir.c_str(), "r");
FILE *out = fopen(FileUtils::getInstance()->getSuitableFOpen(dir).c_str(), "r");
if(!out)
{
@ -398,7 +398,7 @@ bool AssetsManager::uncompress()
}
// Create a file to store current file.
FILE *out = fopen(fullPath.c_str(), "wb");
FILE *out = fopen(FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str(), "wb");
if (! out)
{
CCLOG("can not open destination file %s", fullPath.c_str());
@ -517,7 +517,7 @@ bool AssetsManager::downLoad()
{
// Create a file to save package.
const string outFileName = _storagePath + TEMP_PACKAGE_FILE_NAME;
FILE *fp = fopen(outFileName.c_str(), "wb");
FILE *fp = fopen(FileUtils::getInstance()->getSuitableFOpen(outFileName).c_str(), "wb");
if (! fp)
{
Director::getInstance()->getScheduler()->performFunctionInCocosThread([&, this]{

View File

@ -355,7 +355,7 @@ bool AssetsManagerEx::decompress(const std::string &zip)
}
// Create a file to store current file.
FILE *out = fopen(fullPath.c_str(), "wb");
FILE *out = fopen(FileUtils::getInstance()->getSuitableFOpen(fullPath).c_str(), "wb");
if (!out)
{
CCLOG("AssetsManagerEx : can not create decompress destination file %s\n", fullPath.c_str());

View File

@ -259,11 +259,11 @@ void Downloader::prepareDownload(const std::string &srcUrl, const std::string &s
const std::string outFileName = storagePath + TEMP_EXT;
if (_supportResuming && resumeDownload && _fileUtils->isFileExist(outFileName))
{
fDesc->fp = fopen(outFileName.c_str(), "ab");
fDesc->fp = fopen(FileUtils::getInstance()->getSuitableFOpen(outFileName).c_str(), "ab");
}
else
{
fDesc->fp = fopen(outFileName.c_str(), "wb");
fDesc->fp = fopen(FileUtils::getInstance()->getSuitableFOpen(outFileName).c_str(), "wb");
}
if (!fDesc->fp)
{