Xir*_*dus 7 c++ encoding locale utf-8 c++11
我正在编写一个处理文件和目录的可移植库.我想使用UTF-8作为输入(目录路径)和输出(文件路径).问题是,Windows让我可以选择使用UTF-16-UCS-2和代码页.所以我必须将我的所有UTF-8字符串转换为UTF-16,将它们传递给WinAPI,然后将结果转换回UTF-8.C++ 11似乎<locale>
只为此提供了库,除了我所理解的,没有任何预定义的特化使用UTF-8作为内部(即我的)编码 - 最接近的是UTF-16到UTF -8,这与我想要的完全相反.所以这是第一个问题:
1)如何使用codecvt thingamajigs将我的UTF-8字符串转换为UTF-16进行WinAPI调用,UTF-16结果返回UTF-8?
另一个问题:我也在瞄准Linux.在Linux上,对许多不同的语言环境有很好的支持 - 我不希望有任何不同.希望每个人都在他们的Linux机器上使用UTF-8,但没有严格的保证.所以我认为扩展上面特定于Windows的行为并始终执行UTF-8到系统区域设置编码是一个好主意.除了我没有看到在C++ 11的<locale>
库中有任何方法来获得当前的系统编码!默认的std :: locale构造函数使用自己定义的语言环境,如果不这样做,它将返回经典的"C"语言环境.并且没有其他我知道的吸气剂.所以这是第二个问题:
2)如何检测当前系统区域设置?什么东西<locale>
?也许一些标准的C库函数,或者(在这种情况下可移动性较差)POSIX API中的东西?
leg*_*ize -1
标准库中这些设施的设计假设多字节字符编码(如UTF-8)仅用于外部存储(即磁盘上文件中的字节序列)并且内存中的所有字符大小都是统一的。这样一来,诸如此类的事物std::basic_string<T>::operator[]
就可以按照与标准所施加的性能约束一致的方式运行。因此,虽然您可以使用以 UTF-8 或其他 MBCS(如日语)编码的文件,但内存中的字符串应该是char
、char16_t
或。char32_t
wchar_t
这就是为什么您在标准库中找不到与您想要执行的操作匹配的原因,因为内存中的字符串不打算以 UTF-8 存储。这也类似于其他语言,例如 Java,其中磁盘上的数据被解释为字节流,并将它们转换为字符串,您需要告诉某些组件字节流的预期字符编码。某些操作系统可能会将 UTF-8 字符串填充到 中argv[]
,但这是非标准的。WinMain
这就是Windows 上启用 Unicode 的入口点提供NUL
终止指针wchar_t
而不是char*
指向 UTF-8 编码字符串的原因。
IBM 的International Components for Unicode库提供了一整套组件,这些组件是对 C++ 标准库的补充,并且旨在与 C++ 标准库配合使用。我会看看他们的代码转换工具。虽然该标准定义了<locale>
用于代码转换的工具,但它不保证存在从 UTF-8 映射到 、 或 的代码char16_t
转换char32_t
工具wchar_t
。如果存在这种情况,您只能根据实现的详细信息来获取它。ICU 库为任何 C++ 实现可移植地提供此功能。它得到了很好的支持和使用,并且不太可能在将 UTF-8 字符串解码为适当的宽于char
字符串时出现错误。
Konrad 在评论中提到了 UTF-8 Anywhere 宣言。这是一本有趣的读物,他们将您引向Boost.Nowide库(尚未正式成为 boost 的一部分)以获得您上面引用的问题的解决方案。
请注意,我的回答只是对现有 C++ 标准库类工作方式的描述std::basic_string<T>
。这并不是针对 UTF-8、Unicode 或其他任何内容的建议。引用的宣言同意我的观点,即这些东西根本无法以这种方式工作,如果您想在任何地方使用 UTF-8,那么您需要其他东西。