【问题标题】:What is the Windows equivalent for en_US.UTF-8 locale?en_US.UTF-8 语言环境的 Windows 等效项是什么?
【发布时间】:2011-05-18 11:52:52
【问题描述】:

如果我想在 Windows 上进行以下工作,正确的语言环境是什么以及如何检测它是否实际存在: Does this code work universaly, or is it just my system?

【问题讨论】:

    标签: c++ windows unicode utf-8 locale


    【解决方案1】:

    尽管对命名语言环境没有很好的支持,但 Visual Studio 2010 确实包含 C++11 所需的 UTF-8 转换方面:std::codecvt_utf8 用于 UCS2,std::codecvt_utf8_utf16 用于 UTF-16:

    #include <fstream>
    #include <iostream>
    #include <string>
    #include <locale>
    #include <codecvt>
    void prepare_file()
    {
        // UTF-8 data
        char utf8[] = {'\x7a',                       // latin small letter 'z' U+007a
                       '\xe6','\xb0','\xb4',         // CJK ideograph "water"  U+6c34
                       '\xf0','\x9d','\x84','\x8b'}; // musical sign segno U+1d10b
        std::ofstream fout("text.txt");
        fout.write(utf8, sizeof utf8);
    }
    void test_file_utf16()
    {
        std::wifstream fin("text.txt");
        fin.imbue(std::locale(fin.getloc(), new std::codecvt_utf8_utf16<wchar_t>));
        std::cout << "Read from file using UTF-8/UTF-16 codecvt\n";
        for(wchar_t c; fin >> c; )
            std::cout << std::hex << std::showbase << c << '\n';
    }
    void test_file_ucs2()
    {
        std::wifstream fin("text.txt");
        fin.imbue(std::locale(fin.getloc(), new std::codecvt_utf8<wchar_t>));
        std::cout << "Read from file using UTF-8/UCS2 codecvt\n";
        for(wchar_t c; fin >> c; )
            std::cout << std::hex << std::showbase << c << '\n';
    }
    int main()
    {
        prepare_file();
        test_file_utf16();
        test_file_ucs2();
    }
    

    此输出,在我的 Visual Studio 2010 EE SP1 上

    Read from file using UTF-8/UTF-16 codecvt
    0x7a
    0x6c34
    0xd834
    0xdd0b
    Read from file using UTF-8/UCS2 codecvt
    0x7a
    0x6c34
    0xd10b
    Press any key to continue . . .
    

    【讨论】:

      【解决方案2】:

      【讨论】:

      • @Nemanja Trifunovic:这正是不是博客的重点。对于像 MessageBoxW 这样的每个 UTF-16 API,都有一个“ANSI”变体 MessageBoxA,它将使用当前的“ANSI”代码页进行 8 位到 UTF-16 的转换。但是,您不能使用 UTF-8 作为当前的“ANSI”代码页。但是,MultiByteToWideChar 不使用当前的 ANSI 代码页。它的第一个参数是要使用的代码页,there UTF-8 (65001) 是允许的。
      • @MSalters:博客的重点是代码页 65001 不能是 ACP,这意味着它不能用作 C++ 标准库语言环境。我提到的 UTF-8 UTF-16 转换不是博客的重点,而是我对如何在 Windows 上使用 UTF-8 的问题的回答。更简短的回答是:不要在 Windows 上使用 C++ 标准库进行 IO。
      • @Let_Me_Be:基本上,这归结为 Windows 上的 wchar_t 专门定义为 16 位类型。 C(和 C++)标准要求 wchar_t 能够保存 all 支持的编码中的 any 有效字符。但是没有办法将所有的 Unicode 字符编码为 16 位 - 就是无法做到。因此,Windows C 和 C++ 库实际上支持任何类型的 Unicode。如果你想在 Windows 上使用 Unicode,你必须跳出 C 和 C++ 库。是的,这很愚蠢,但是您对 Microsoft 有什么期望? :P
      • @Let_Me_Be:您混淆了 16 位 wchar_t 和 UTF-16。它们不是同一件事。 UTF-8 和 UTF-16 是编码所有 Unicode 代码点的两种不同方式(其中 far 不仅仅是 65535)。您至少需要 24 位来表示所有 1,000,000 多个 Unicode 代码点。 UTF-16 中的“16”not 表示所有字符都只能使用 16 位表示(例如,某些 Unicode 字符需要 32 位 [两个 16 位 代码单元 ]使用 UTF-16 编码时)。但是 C++ 库需要 wchar_t 才能唯一地表示 每个 支持的字符。
      • @Let_Me_Be:我确实阅读了您的链接问题,但您似乎没有理解那里的正确答案。部分(甚至全部)Windows API 可以将 wchar_t 字符串解释为 UTF-16 编码数据,但C 和 C++ 库 。如果他们这样做了,那么您可以使用 UTF-8 作为 C 和 C++ 库的语言环境。但是,你不能。这就是您的问题的答案;)
      【解决方案3】:

      在过去,UTF-8(和其他一些代码页)不允许作为系统语言环境,因为

      Microsoft 表示,UTF-8 语言环境可能会破坏某些函数,因为它们被编写为假设多字节编码每个字符使用不超过 2 个字节,因此代码页具有更多字节,例如 UTF-8(以及 GB 18030、cp54936 ) 无法设置为语言环境。

      https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows#UTF-8

      不过,微软逐渐引入了UTF-8 locale support,并开始再次推荐 ANSI API (-A),而不是像以前那样的 Unicode (-W) 版本

      直到最近,Windows 一直强调“Unicode”-W 变体而不是 -A API。但是,最近的版本使用 ANSI 代码页和 -A API 作为向应用程序引入 UTF-8 支持的一种方式。如果为 UTF-8 配置 ANSI 代码页,则-A API 以 UTF-8 运行。此模型的优势在于支持使用-A API 构建的现有代码,无需任何代码更改。

      -A vs. -W APIs


      首先,他们添加了一个“Beta:使用 Unicode UTF-8 支持全球语言”复选框,因为 Windows 10 Insider build 17035 用于将语言环境代码页设置为 UTF-8

      要打开该对话框,请打开开始菜单,输入“区域”并选择区域设置 > 其他日期、时间和区域设置 > 更改日期、时间或数字格式 > 管理

      启用后,您可以像往常一样拨打setlocal

      从 Windows 10 build 17134(2018 年 4 月更新)开始,通用 C 运行时支持使用 UTF-8 代码页。这意味着传递给 C 运行时函数的 char 字符串将需要 UTF-8 编码的字符串。要启用 UTF-8 模式,请在使用 setlocale 时使用“UTF-8”作为代码页。例如,setlocale(LC_ALL, ".utf8") 将使用当前默认的 Windows ANSI 代码页 (ACP) 作为语言环境,使用 UTF-8 作为代码页。

      UTF-8 Support

      您也可以在旧的 Windows 版本中使用它

      要在 Windows 10 之前的操作系统(例如 Windows 7)上使用此功能,您必须使用 app-local deployment 或使用版本 17134 或更高版本的 Windows SDK 进行静态链接。对于 17134 之前的 Windows 10 操作系统,仅支持静态链接。


      在 2019 年后期,他们增加了程序使用 UTF-8 语言环境的功能,甚至无需在上面设置 UTF-8 beta 标志。使用 MSVC 编译时可以使用 /execution-charset:utf-8/utf-8 选项,或者在 appxmanifest 中设置 ActiveCodePage 属性

      【讨论】:

      • 新功能的精彩回顾!令人惊讶的是,他们花了这么长时间才说“让我们在 C 字符串中使用 utf-8”。 /utf-8 选项似乎与复选框无关。它设置了二进制文件的执行和源字符集,但我可能错了。
      【解决方案4】:

      根据MSDN,它将被命名为“english_us.65001”。但是代码页 65001 在 Windows 上有些不稳定。

      【讨论】:

      • 你能否对“有点片状”发表更多评论?
      • @Let_Me_Be:我无法比google.com/search?q=site%3Ablogs.msdn.com+65001总结得更好
      • @MSalters 很抱歉,但我找不到任何最新且足够详细的内容。我从阅读的简短博客文章中了解到,Windows 根本不支持 UTF-8(这没有任何意义)。
      • @Let_Me_Be:它没有隐式支持。你不能打电话给MessageBoxA("Hellö")。但是,它有明确的支持:MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, utf8input.c_str(), ...
      • @Let_Me_Be:所有这些答案试图说明的是 Windows 上没有 utf-8 语言环境。
      猜你喜欢
      • 2019-09-04
      • 2018-09-21
      • 2017-11-15
      • 2021-04-07
      • 2018-09-21
      • 2017-06-21
      • 2019-07-31
      • 2021-06-20
      相关资源
      最近更新 更多