繁体   English   中英

使用标准C ++ wifstream读取UTF-8文本并转换为UTF-16

[英]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_tchar32_t ,它们可以使用自己的可移植代码,但是标准缺少一些位以使iostream可以与这些字符类型一起使用,并且实现也不完全支持指定的内容。

VS我认为仍然将char16_tchar32_t实现为typedef,因此使用它们的模板特化不起作用(即使专业化确实存在,如果你查看标题,它们只是因为编译器无法处理而被删除他们)。 libstdc ++尚未实现模板特化,即使它支持char16_tchar32_t作为实际类型。 我所知道的最完整的实现是带有合适编译器(gcc或clang)的libc ++,但即便如此,仍然缺少<cuchar>头。

由于实现支持是有限的,除了使用它们作为跨平台的用户代码中的一致表示(尽管这甚至单独使用)之外,这种方式可以防止可移植代码对这些做很多事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM