closed #2440: Files with Non-ascii path can't be found on Windows.

This commit is contained in:
James Chen 2013-07-29 18:27:26 +08:00
parent 1c2b89e431
commit 2566f74cd7
2 changed files with 131 additions and 1 deletions

View File

@ -43,6 +43,36 @@ static void _checkPath()
}
}
// D:/aaa/bbb/ccc/ddd/abc.txt --> D:\aaa\bbb\ccc\ddd\abc.txt
static inline std::string convertPathFormatToWindowStyle(const std::string& path)
{
std::string ret = path;
int len = ret.length();
for (int i = 0; i < len; ++i)
{
if (ret[i] == '/')
{
ret[i] = '\\';
}
}
return ret;
}
// D:\aaa\bbb\ccc\ddd\abc.txt --> D:/aaa/bbb/ccc/ddd/abc.txt
static inline std::string convertPathFormatToUnixStyle(const std::string& path)
{
std::string ret = path;
int len = ret.length();
for (int i = 0; i < len; ++i)
{
if (ret[i] == '\\')
{
ret[i] = '/';
}
}
return ret;
}
FileUtils* FileUtils::getInstance()
{
if (s_sharedFileUtils == NULL)
@ -81,7 +111,12 @@ bool FileUtilsWin32::isFileExist(const std::string& strFilePath)
{ // Not absolute path, add the default root path at the beginning.
strPath.insert(0, _defaultResRootPath);
}
return GetFileAttributesA(strPath.c_str()) != -1 ? true : false;
convertPathFormatToWindowStyle(strPath);
WCHAR wszBuf[MAX_PATH] = {0};
MultiByteToWideChar(CP_UTF8, 0, strPath.c_str(), -1, wszBuf, sizeof(wszBuf));
return GetFileAttributesW(wszBuf) != -1 ? true : false;
}
bool FileUtilsWin32::isAbsolutePath(const std::string& strPath)
@ -95,6 +130,68 @@ bool FileUtilsWin32::isAbsolutePath(const std::string& strPath)
return false;
}
unsigned char* FileUtilsWin32::getFileData(const char* filename, const char* mode, unsigned long* size)
{
unsigned char * pBuffer = NULL;
CCASSERT(filename != NULL && size != NULL && mode != NULL, "Invalid parameters.");
*size = 0;
do
{
// read the file from hardware
std::string fullPath = fullPathForFilename(filename);
WCHAR wszBuf[MAX_PATH] = {0};
MultiByteToWideChar(CP_UTF8, 0, fullPath.c_str(), -1, wszBuf, sizeof(wszBuf));
HANDLE fileHandle = ::CreateFileW(wszBuf, GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL);
CC_BREAK_IF(fileHandle == INVALID_HANDLE_VALUE);
*size = ::GetFileSize(fileHandle, NULL);
pBuffer = new unsigned char[*size];
DWORD sizeRead = 0;
BOOL successed = FALSE;
successed = ::ReadFile(fileHandle, pBuffer, *size, &sizeRead, NULL);
::CloseHandle(fileHandle);
if (!successed)
{
CC_SAFE_DELETE_ARRAY(pBuffer);
}
} while (0);
if (! pBuffer)
{
std::string msg = "Get data from file(";
// Gets error code.
DWORD errorCode = ::GetLastError();
char errorCodeBuffer[20] = {0};
snprintf(errorCodeBuffer, sizeof(errorCodeBuffer), "%d", errorCode);
msg = msg + filename + ") failed, error code is " + errorCodeBuffer;
CCLOG("%s", msg.c_str());
}
return pBuffer;
}
std::string FileUtilsWin32::getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath)
{
std::string unixFileName = convertPathFormatToUnixStyle(filename);
std::string unixResolutionDirector = convertPathFormatToUnixStyle(resolutionDirectory);
std::string unixSearchPath = convertPathFormatToUnixStyle(searchPath);
return FileUtils::getPathForFilename(unixFileName, unixResolutionDirector, unixSearchPath);
}
std::string FileUtilsWin32::getFullPathForDirectoryAndFilename(const std::string& strDirectory, const std::string& strFilename)
{
std::string dosDirectory = convertPathFormatToWindowStyle(strDirectory);
std::string dosFilename = convertPathFormatToWindowStyle(strFilename);
return FileUtils::getFullPathForDirectoryAndFilename(dosDirectory, dosFilename);
}
string FileUtilsWin32::getWritablePath()
{
// Get full path of executable, e.g. c:\Program Files (x86)\My Game Folder\MyGame.exe

View File

@ -49,6 +49,39 @@ public:
virtual std::string getWritablePath();
virtual bool isFileExist(const std::string& strFilePath);
virtual bool isAbsolutePath(const std::string& strPath);
protected:
/**
* Gets resource file data
*
* @param[in] filename The resource file name which contains the path.
* @param[in] pszMode The read mode of the file.
* @param[out] pSize If the file read operation succeeds, it will be the data size, otherwise 0.
* @return Upon success, a pointer to the data is returned, otherwise NULL.
* @warning Recall: you are responsible for calling delete[] on any Non-NULL pointer returned.
*/
virtual unsigned char* getFileData(const char* filename, const char* mode, unsigned long * size) override;
/**
* Gets full path for filename, resolution directory and search path.
*
* @param filename The file name.
* @param resolutionDirectory The resolution directory.
* @param searchPath The search path.
* @return The full path of the file. It will return an empty string if the full path of the file doesn't exist.
*/
virtual std::string getPathForFilename(const std::string& filename, const std::string& resolutionDirectory, const std::string& searchPath) override;
/**
* Gets full path for the directory and the filename.
*
* @note Only iOS and Mac need to override this method since they are using
* `[[NSBundle mainBundle] pathForResource: ofType: inDirectory:]` to make a full path.
* Other platforms will use the default implementation of this method.
* @param strDirectory The directory contains the file we are looking for.
* @param strFilename The name of the file.
* @return The full path of the file, if the file can't be found, it will return an empty string.
*/
virtual std::string getFullPathForDirectoryAndFilename(const std::string& strDirectory, const std::string& strFilename) override;
};
// end of platform group