请考虑以下代码:
#include <iostream>
#include <boost\locale.hpp>
#include <Windows.h>
#include <fstream>
std::string ToUtf8(std::wstring str)
{
std::string ret;
int len = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0, NULL, NULL);
if (len > 0)
{
ret.resize(len);
WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.length(), &ret[0], len, NULL, NULL);
}
return ret;
}
int main()
{
std::wstring wfilename = L"D://Private//Test//एउटा फोल्दर//भित्रको फाईल.txt";
std::string utf8path = ToUtf8(wfilename );
std::ifstream iFileStream(utf8path , std::ifstream::in | std::ifstream::binary);
if(iFileStream.is_open())
{
std::cout << "Opened the File\n";
//Do the work here.
}
else
{
std::cout << "Cannot Opened the file\n";
}
return 0;
}
如果我正在运行该文件,则无法打开文件,因此进入else
块。即使使用boost::locale::conv::from_utf(utf8path ,"utf_8")
代替utf8path
也无效。如果我考虑使用wifstream
并使用wfilename
作为参数,则代码可以正常运行,但我不会这样做。想要使用wifstream
。有没有办法打开名称为utf8
编码的文件?我正在使用Visual Studio 2010
。
答案 0 :(得分:20)
在Windows上,必须使用8位ANSI(并且必须匹配用户的语言环境)或UTF16用于文件名,没有其他选项可用。您可以在主代码中继续使用string
和UTF8,但在打开文件时必须将UTF8文件名转换为UTF16。效率较低,但这就是你需要做的事情。
幸运的是,VC ++对std::ifstream
和std::ofstream
的实现具有非标准的构造函数和open()
方法的重载UTF16文件名的wchar_t*
个字符串。
explicit basic_ifstream(
const wchar_t *_Filename,
ios_base::openmode _Mode = ios_base::in,
int _Prot = (int)ios_base::_Openprot
);
void open(
const wchar_t *_Filename,
ios_base::openmode _Mode = ios_base::in,
int _Prot = (int)ios_base::_Openprot
);
void open(
const wchar_t *_Filename,
ios_base::openmode _Mode
);
explicit basic_ofstream(
const wchar_t *_Filename,
ios_base::openmode _Mode = ios_base::out,
int _Prot = (int)ios_base::_Openprot
);
void open(
const wchar_t *_Filename,
ios_base::openmode _Mode = ios_base::out,
int _Prot = (int)ios_base::_Openprot
);
void open(
const wchar_t *_Filename,
ios_base::openmode _Mode
);
您必须使用#ifdef
检测Windows编译(不幸的是,不同的C ++编译器识别不同)并在打开文件时暂时将UTF8字符串转换为UTF16。
#ifdef _MSC_VER
std::wstring ToUtf16(std::string str)
{
std::wstring ret;
int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
if (len > 0)
{
ret.resize(len);
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &ret[0], len);
}
return ret;
}
#endif
int main()
{
std::string uft8path = ...;
std::ifstream iFileStream(
#ifdef _MSC_VER
ToUtf16(uft8path).c_str()
#else
uft8path.c_str()
#endif
, std::ifstream::in | std::ifstream::binary);
...
return 0;
}
请注意,这只能保证在VC ++中有效。其他用于Windows的C ++编译器无法保证提供类似的扩展。