Fra*_*une 6 c++ windows boost locale boost-filesystem
我正在修复一个大型开源跨平台应用程序,以便它可以处理 Windows 上包含非 ANSI 字符的文件路径。
更新:
根据到目前为止我得到的答案和评论(谢谢!)我觉得我应该澄清一些观点:
我无法修改几十个第三方库的代码来使用std::wchar_t。这不是一个选择。该解决方案必须与普通的 ol'等一起std::fopen()使用。std::ifstream
我在下面概述的解决方案的运行率为 99%,至少在我正在开发的系统上(Windows 10 版本 1909,内部版本 18363.535)。我还没有在任何其他系统上进行过测试。
唯一剩下的问题,至少在我的系统上,基本上是数字格式,我希望替换方面std::numpunct能够解决问题(但我还没有成功)。
我当前的解决方案包括:
将 Windows 上的类别的C 区域设置设置为.UTF-8(LC_CTYPE所有其他类别均设置为C应用程序所需的区域设置):
// Required by the application.
std::setlocale(LC_ALL, "C");
// On Windows, we want std::fopen() and other functions dealing with strings
// and file paths to accept narrow-character strings encoded in UTF-8.
#ifdef _WIN32
{
#ifndef NDEBUG
char* new_ctype_locale =
#endif
std::setlocale(LC_CTYPE, ".UTF-8");
assert(new_ctype_locale != nullptr);
}
#endif
Run Code Online (Sandbox Code Playgroud)
配置boost::filesystem::path使用en_US.UTF-8区域设置,以便它也可以处理包含非 ANSI 字符的路径:
boost::filesystem::path::imbue(std::locale("en_US.UTF-8"));
Run Code Online (Sandbox Code Playgroud)
最后缺少的一点是使用 C++ 流修复文件 I/O,例如
std::ifstream istream(filename);
Run Code Online (Sandbox Code Playgroud)
最简单的解决方案可能是在应用程序开头设置全局 C++ 区域设置:
std::locale::global(std::locale("en_US.UTF-8"));
Run Code Online (Sandbox Code Playgroud)
然而,这会扰乱数字的格式,例如 1234.56 被格式化为 1,234.56。
是否有一个区域设置仅将编码指定为 UTF-8 而不会弄乱数字格式(或其他内容)?
基本上我正在寻找C.UTF-8区域设置,但 Windows 上似乎不存在。
更新:我想一个解决方案是重置语言环境的一些(大多数?全部?)方面,但我很难找到有关如何做到这一点的信息。
Windows API不尊重CRT语言环境,并且CRTfopen等的实现直接调用narrow-char API,因此更改语言环境不会影响编码。
但是,Windows 10 May 2019 Update(版本 1903)在其窄字符 API 中引入了对 UTF-8 的支持。可以通过将适当的清单嵌入到可执行文件中来启用它。不幸的是,它是最近添加的,因此如果您需要针对较旧的系统,则可能不是一个选择。
您的其他选项包括手动转换wchar_t或使用可以为您执行此操作的层(例如 Boost.Filesystem ,甚至更好的是Boost.Nowide)。
| 归档时间: |
|
| 查看次数: |
9623 次 |
| 最近记录: |