“ Windows上的C.UTF-8” C ++语言环境?

问题描述 投票:2回答:2

我正在修复一个大型的开源跨平台应用程序,以便它可以处理Windows上包含非ANSI字符的文件路径。

我当前的解决方案涉及:

  1. 在Windows上将.UTF-8类别的C语言环境设置为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
    
  2. 配置boost::filesystem::path以使用en_US.UTF-8语言环境,以便它也可以处理包含非ANSI字符的路径:

    boost::filesystem::path::imbue(std::locale("en_US.UTF-8"));
    

最后遗漏的一点是使用C ++流修复文件I / O,例如

std::ifstream istream(filename);

最简单的解决方案可能是在应用程序的开头设置全局C ++语言环境:

std::locale::global(std::locale("en_US.UTF-8"));

然而,这弄乱了数字的格式,例如1234.56的格式设置为1,234.56。

是否有一个语言环境just将编码指定为UTF-8,而不会弄乱数字格式(或其他东西)?

基本上,我正在寻找C.UTF-8语言环境,但是Windows似乎不存在。

更新:我想一种解决方案是重设语言环境的某些(大部分?全部?)方面,但是我很难找到有关如何执行此操作的信息。

c++ windows boost locale boost-filesystem
2个回答
2
投票

没关系的语言环境。

在Windows上,您应该使用Microsoft's extension,该构造函数将const std::wchar_t*(预期指向UTF-16的指针)添加到std::ifstream

希望您的所有字符串都是UTF-8,或其他一些一致且合理的编码。

因此,只需抓住一个UTF-8→UTF-16转换器(它们是轻量级的,并将文件名作为UTF-16(在std::ifstream中)传递给std::wchar_t*

((请确保将其压缩为#ifdef,以便在任何其他平台上都不会尝试。)

出于相同的原因,您也应以相同的方式使用_wfopen代替_wfopen

就是这样。


1
投票

Windows API不尊重CRT语言环境,std::fopen等的CRT实现直接调用窄字符API,因此更改语言环境不会影响编码。

但是,Windows 10 May 2019更新(版本1903)fopen。可以通过将适当的清单嵌入可执行文件中来启用它。不幸的是,这是一个非常新的功能,因此如果您需要定位较旧的系统,则可能无法选择。

您的其他选择包括手动转换为introduced a support for UTF-8 in its narrow-char APIs或使用为您完成此操作的层(例如Boost.Filesystem,或更佳的是wchar_t)。

© www.soinside.com 2019 - 2024. All rights reserved.