![](/img/trans.png)
[英]C++ Reading UTF-8 file OK, converting to UTF-16 OK, writing back to file NOT OK
[英]Reading UTF-8 text and converting to UTF-16 using standard C++ wifstream
我想从使用UTF-8编码的文件中读取一些文本并使用std::wifstream
将其转换为UTF-16,如下所示:
//
// Read UTF-8 text and convert to UTF-16
//
std::wifstream src;
src.imbue(std::locale("???")); // UTF-8 ???
src.open("some_text_file_using_utf8");
std::wstring line; // UTF-16 string
while (std::getline(src, line))
{
... do something processing the UTF-16 string ...
}
是否有UTF-8转换的标准区域设置名称?
是否可以使用std::locale
实现该目标?
我正在使用Visual Studio 2013。
注意:
我知道I / O流往往很慢,并且可以使用Win32内存映射文件来更快地读取,并使用MultiByteToWideChar()
Win32 API进行转换等。
但对于这个特殊情况,我想要一个只使用标准C ++及其标准库的解决方案, 而不需要 Boost。
如果C ++标准库不能这样做, 第二个选项是使用Boost ; 在这种情况下,我应该使用哪个Boost库?
这适用于使用Visual Studio的Windows,我认为可以追溯到VS2010
#include <locale> // consume_header, locale
#include <codecvt> // codecvt_utf8_utf16
src.imbue(std::locale(
src.getloc(),
new std::codecvt_utf8_utf16<wchar_t, 0x10FFFF, std::consume_header>));
由于Windows使用16位wchar_t
并且通常使用UTF-16作为宽字符编码,因此在该环境中工作得很好。 (因为我假设一个Windows环境,我的例子包括consume_header
来处理Windows向UTF-8数据添加标题的惯例)。
在其他平台上, wchar_t
通常是32位,虽然您可以在这样的32位代码单元中存储UTF-16代码单元值,但是没有其他任何东西可以写入期望这样的东西。 在具有32位wchar_t
的平台上,您可能更喜欢使用std::codecvt_utf8<wchar_t>
来生成UTF-32宽字符串。
理想情况下,为了便携性,您需要的是一个codecvt方面,它知道如何从UTF-8转换为语言环境的wchar_t
编码或宽执行编码。 然而,问题在于,不需要任何宽编码来支持UTF-8中可表示的整个字符范围。 底线是wchar_t
对于指定的可移植代码不是特别有用。
但是,如果你坚持使用UTF-16或UTF-32的平台取决于wchar_t
的大小,那么可能有用的一个技巧是:
template <int N> struct get_codecvt_utf8_wchar_impl;
template <> struct get_codecvt_utf8_wchar_impl<16> {
using type = std::codecvt_utf8_utf16<wchar_t>;
};
template <> struct get_codecvt_utf8_wchar_impl<32> {
using type = std::codecvt_utf8<wchar_t>;
};
using codecvt_utf8_wchar = get_codecvt_utf8_wchar_impl<
sizeof(wchar_t) * CHAR_BIT>::type;
src.imbue(std::locale(src.getloc(), new codecvt_utf8_wchar));
您还可以使用char16_t
和char32_t
,它们可以使用自己的可移植代码,但是标准缺少一些位以使iostream可以与这些字符类型一起使用,并且实现也不完全支持指定的内容。
VS我认为仍然将char16_t
和char32_t
实现为typedef,因此使用它们的模板特化不起作用(即使专业化确实存在,如果你查看标题,它们只是因为编译器无法处理而被删除他们)。 libstdc ++尚未实现模板特化,即使它支持char16_t
和char32_t
作为实际类型。 我所知道的最完整的实现是带有合适编译器(gcc或clang)的libc ++,但即便如此,仍然缺少<cuchar>
头。
由于实现支持是有限的,除了使用它们作为跨平台的用户代码中的一致表示(尽管这甚至单独使用)之外,这种方式可以防止可移植代码对这些做很多事情。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.