在 c++ Windows 中打开 utf8 编码的文件名
Open utf8 encoded filename in c++ Windows
请考虑以下代码:
#include <iostream>
#include <boostlocale.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 Filen";
//Do the work here.
}
else
{
std::cout << "Cannot Opened the filen";
}
return 0;
}
如果我正在运行该文件,则无法打开该文件,从而进入else
块。即使使用boost::locale::conv::from_utf(utf8path ,"utf_8")
而不是utf8path
也不起作用。如果我考虑使用 wifstream
并使用 wfilename
作为其参数,则代码有效,但我不想使用 wifstream
.有没有办法打开名称utf8
编码的文件?我正在使用Visual Studio 2010
.
在Windows上,您必须使用8位ANSI(并且必须与用户的语言环境匹配)或UTF-16作为文件名,没有其他选项可用。 您可以在主代码中继续使用 string
和 UTF-8,但在打开文件时必须将 UTF-8 文件名转换为 UTF-16。 效率较低,但这是您需要做的。
幸运的是,VC++ 的 std::ifstream
和 std::ofstream
实现具有非标准构造函数重载,并open()
接受 UTF-16 文件名的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++编译器识别不同),并在打开文件时临时将 UTF-8 字符串转换为 UTF-16。
#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 utf8path = ...;
std::ifstream iFileStream(
#ifdef _MSC_VER
ToUtf16(utf8path).c_str()
#else
utf8path.c_str()
#endif
, std::ifstream::in | std::ifstream::binary);
...
return 0;
}
请注意,这只能保证在 VC++ 中有效。 其他适用于 Windows 的C++编译器不保证提供类似的扩展。
更新:从 Windows 10 预览体验成员预览版版本 17035 开始,Microsoft现在支持 UTF-8 作为用户可以将其区域设置的系统范围编码。 从 Windows 10 版本 1903(内部版本 18362)开始,应用程序现在可以通过其应用清单选择使用 UTF-8 作为进程范围的代码页,即使用户区域设置未设置为 UTF-8。 这些功能允许基于 ANSI 的 API(如 CreateFileA()
,std::ifstream
/std::ofstream
内部使用)处理 UTF-8 字符串。 因此,从理论上讲,打开此功能后,您可能能够将 UTF-8 编码字符串传递给 std::ifstream
/std::ofstream
并且它将"正常工作"。 我无法确认这一点,因为这在很大程度上取决于实现。 坚持传入UTF-16文件名会更安全,因为这是Windows的本机编码,ANSI API将简单地在内部转换为。
您可以在 C++14/17 中使用std::filesystem::u8path
:
std::filesystem::path pa = std::filesystem::u8path((const char*)yourStdStringPath.c_str());
std::ofstream ofs(pa);
它在 C++20 中已弃用,因为您可以使用 u8 前缀。
- C++和带有国家符号的文件路径(也许用 UTF8 编码)
- MSVC UTF8字符串编码使用了不正确的代码点
- 使用C++将越南语字符从ISO88591、UTF8、UTF16BE、UTF16LE和UTF16编码为十六进制,反之亦然
- 有没有办法将 vector<unsigned char> 插入 postgresql 表中,具有 bytea 属性,没有 UTF8 编码错误?
- 使用具有 UTF8 编码的源文件将 UTF8 符号打印到 Windows 控制台
- 比较UTF8编码的字符
- 处理UTF8编码的char*数组
- 如何将文本从CP437编码转换为UTF8编码
- 将utf8编码的字符串转换为本地8位编码的字符串,并将无法确定的字符替换为空白
- Rapidjson根本不编码utf8序列
- 从 Mac OS Roman 到 UTF8 的编码
- UTF8 文本编码 - Windows Phone 8.1 C++
- 如何在C++中将文件编码格式设置为UTF8
- 如何轻松检测字符串中的 utf8 编码
- 初始化 utf8 编码字符串 c++11
- 编码.Utf8将逗号转换为c#中的一些特殊字符
- utf8编码算法与utf16算法
- C++字符串编码UTF8 /Unicode
- 在 c++ Windows 中打开 utf8 编码的文件名
- 如何在可视C++中使用 UTF8 编码