我正在编写一个处理文件和目录的可移植库。我想使用UTF-8作为输入(目录路径)和输出(文件路径)。问题是,Windows给了我在UTF-16-那个将要使用的UCS-2和代码页之间的选择。所以我必须将我所有的UTF-8字符串转换为UTF-16,将它们传递给WinAPI,并将结果转换回UTF-8。C++11似乎只是为此提供了<locale>库,除了我所理解的之外,没有一个预定义的专门化使用UTF-8作为内部的(即。最接近的是UTF-16到-UTF-8,这与我想要的完全相反。这是第一个问题:
1)如何使用编解码器将UTF-8字符串转换为WinAPI调用的UTF-16,并将UTF-16的结果转换为UTF-8?
另一个问题是:我也在处理Linux。在Linux上,有一个非常好的支持许多不同的地区-我不想有任何不同。希望每个人都能在他们的Linux机器上使用UTF-8,但是没有严格的保证。因此,我认为扩展上述Windows特定行为是个好主意,并且总是执行UTF-8到系统-地区编码。不过,我看不出C++11的<locale>库中有任何方法可以获得当前的系统编码!默认std::locale构造函数自行指定区域设置,如果不这样做,它将返回经典的"C“区域设置。我也不知道还有其他的得奖者。这是第二个问题:
2)如何检测当前的系统环境?<locale>里有什么吗?也许是一些标准的C库函数,或者是POSIX API中的一些东西(在这种情况下可移植性较低,但还可以)?
发布于 2014-08-08 18:14:45
标准库中这些工具的设计假定多字节字符编码(如UTF-8)仅用于外部存储(即磁盘上文件中的字节序列),并且内存中的所有字符大小一致。这样,像std::basic_string<T>::operator[]这样的事情就可以以一种与标准所施加的性能约束相一致的方式运行。因此,虽然您可以使用UTF-8或其他MBCS编码的文件(就像日语中的那样),但是内存中的字符串应该是char、char16_t、char32_t或wchar_t。
这就是为什么在标准库中找不到要做的匹配的原因,因为内存中的字符串不打算存储在UTF-8中。这与其他语言类似,例如Java,其中磁盘上的数据被解释为字节流,要将它们转换为字符串,您需要告诉某些组件字节流的预期字符编码。有些操作系统可能会将UTF-8字符串插入argv[],但这是不标准的.这就是为什么WinMain上启用Unicode的入口点提供了指向wchar_t的NUL终止指针,而不是指向UTF-8编码字符串的char*。
IBM的Unicode的国际组件库提供了一整套组件,它们是C++标准库的补充和设计。我会看看他们的代码转换工具。虽然标准在<locale>中定义了用于代码转换的工具,但它并不保证有任何代码转换工具可以从UTF-8映射到char16_t、char32_t或wchar_t。如果存在这样的事情,则只能根据实现的细节来获得它。ICU库为任何C++实现提供可移植的此功能。它得到了良好的支持和良好的使用,并且不太可能有错误将UTF-8字符串解码成比-char字符串更宽的字符串。
康拉德在评论中提到了UTF-8“任何地方宣言”。这是一个有趣的阅读,他们向您指出Boost.Nowide库(尚未正式成为boost的一部分),以获得解决上述问题的方法。
请注意,我的回答只是描述了现有的C++标准库类(如std::basic_string<T> )的工作方式。它不是针对UTF-8、Unicode或其他任何东西的建议。引用的宣言同意我的观点,即这些东西根本就不是这样的,如果你想在任何地方使用UTF-8,那么你需要其他的东西。
https://stackoverflow.com/questions/24722678
复制相似问题