在C++中读写/打印UTF-8 11

问题描述:

我一直在探索C++ 11的新Unicode功能,虽然other C++11 encoding questions已经非常有帮助,但我对cppreference以下代码段有疑问。代码写入并立即读取以UTF-8编码保存的文本文件。在C++中读写/打印UTF-8 11

// Write 
std::ofstream("text.txt") << u8"z\u6c34\U0001d10b"; 

// Read 
std::wifstream file1("text.txt"); 
file1.imbue(std::locale("en_US.UTF8")); 
std::cout << "Normal read from file (using default UTF-8/UTF-32 codecvt)\n"; 
for(wchar_t c; file1 >> c;) // ? 
    std::cout << std::hex << std::showbase << c << '\n'; 

是很简单的,为什么是wchar_t需要在for环路我的问题? A u8字符串文字可以使用简单的char *来声明,而UTF-8编码的位布局应该告诉系统字符的宽度。看起来有一些从UTF-8到UTF-32的自动转换(因此wchar_t),但如果是这种情况,为什么需要转换?

+0

这取决于很多事情。值得注意的是,正确的UTF8行为在控制台应用程序中使用Windows时不是不可能的(如果不是不可能的话)(要求_至少有很多非标准API调用IIRC) – sehe 2013-03-18 10:57:10

+1

使用'wchar_t'是因为使用了wifstream而wifstream执行你提到的“一些自动转换”。我的观点是要展示自动转换(为一个特定平台实现)和'codecvt_utf8_utf16'提供的明确的,可移植的,与区域无关的Unicode转换之间的区别。 – Cubbi 2013-03-18 14:29:33

您使用wchar_t,因为您使用wifstream来读取文件;如果您正在使用ifstream进行阅读,则您将使用char,并且类似地使用char16_tchar32_t

假设(作为示例执行),该wchar_t是32位,并且所述本地字符集,它代表是UTF-32(UCS-4),那么这是要读取的文件作为最简单的方法UTF-32;它在这个例子中是这样表示的,以便将文件读作UTF-16。更为便携的方法是明确使用basic_ifstream<char32_t>std::codecvt_utf8<char32_t>,因为这可以保证从UTF-8输入流转换为UTF-32元素。

+1

+1,我写这个例子和对比是我的目标。 – Cubbi 2013-03-18 13:54:02

+0

啊我明白了!因此,总是明确地将UTF-8转换为更宽的'wchar_t',或者使用'ifstream'将原始UTF-8字节提取到本地'char'数组中是否可以接受?我不确定是否从@ Cubbi的例子推断后者是不好的做法,或者它是否超出了范例的范围。 – Ephemera 2013-03-19 00:47:40

+0

@PLPiper是的,你可以随时读取任何多字节编码文件到char数组中,而无需进行任何转换。使用标准C++中的这样的数组没有太多的功能(除了首先转换为宽),但是大量的库需要使用utf8输入。 – Cubbi 2013-03-19 02:26:00

您使用的cppreference代码片段的想法是展示如何将UTF-8文件读取到UTF-16字符串中,这就是为什么他们使用ofstream编写文件,但是使用wifstream读取文件(因此wchar_t) 。