fopen接口默认使用ANSI解析文件路径,如果文件路径(含文件名称)不是ANSI编码的情况下,会出现写文件失败或文件名称乱码的问题。
解决方法有两个:一个是将路径转换为ANSI(存在风险,如果路径中的字符不在ANSI字符集里转换后会乱码);一个是将路径转换为UNICODE(保险),在调用_wfopen_s接口打开文件;
备注:ANSI依赖于操作系统语言,比如中文系统ANSI就是GB2312
代码示例:
bool ANSIToWide(std::wstring& wstr, const std::string& ansi)
{
int size = MultiByteToWideChar(CP_ACP, NULL, ansi.c_str(), ansi.size(), NULL, NULL);
wchar_t* wide = new wchar_t[size];
wmemset(wide, L'\0', size);
size = MultiByteToWideChar(CP_ACP, NULL, ansi.c_str(), ansi.size(), wide, size);
wstr.assign(wide, size);
delete[] wide;
wide = NULL;
return true;
}
// 写文件
bool WriteFile(const std::string& file_path)
{
FILE* file_handle = nullptr;
bool ret = false;
do
{
errno_t err;
// 如果文件路径(含文件名称)的语言不在ANSI字符编码里,会出现写文件失败或文件名称乱码的问题
// ANSI依赖于操作系统语言,比如中文系统ANSI就是GB2312
//err = fopen_s(&file_handle, file_path.c_str(), "a");
wstring wstr;
ANSIToWide(wstr, file_path); // UTF-8编码转宽字节(UTF-16)
err = _wfopen_s(&file_handle, wstr.c_str(), L"a");
if (0 != err)
{
std::cout << "Open file failed, err: " << err << " file path: " << file_path.c_str() << std::endl;
break;
}
std::string data = "test";
size_t size = fwrite(data.c_str(), 1, data.size(), file_handle);
if (size != data.size())
{
std::cout << "Write data to file failed, err: " << err << " data: " << data.c_str() << std::endl;
break;
}
ret = true;
std::cout << "Write data to file success, data: " << data.c_str() << std::endl;
} while (false);
if (nullptr != file_handle)
{
fclose(file_handle);
file_handle = nullptr;
}
return ret;
}