如何使用std :: ifstream读取UTF-8编码的文本文件?

Jae*_*LEE 5 c++ string encoding utf-8 ifstream

我很难解析xml文件。

该文件使用UTF-8编码保存。

可以正确读取普通ASCII,但不能正确读取朝鲜语字符。

因此,我编写了一个简单的程序来读取UTF-8文本文件并打印内容。

文字档(test.txt)

ABC???
Run Code Online (Sandbox Code Playgroud)

测试程序

#include <fstream>
#include <iostream>
#include <string>
#include <iterator>
#include <streambuf>

const char* hex(char c) {
    const char REF[] = "0123456789ABCDEF";
    static char output[3] = "XX";
    output[0] = REF[0x0f & c>>4];
    output[1] = REF[0x0f & c];
    return output;
}

int main() {
    std::cout << "File(ifstream) : ";
    std::ifstream file("test.txt");
    std::string buffer((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
    for (auto c : buffer) {
        std::cout << hex(c)<< " ";
    }
    std::cout << std::endl;
    std::cout << buffer << std::endl;

    //String literal
    std::string str = "ABC???";
    std::cout << "String literal : ";
    for (auto c : str) {
        std::cout << hex(c) << " ";
    }
    std::cout << std::endl;
    std::cout << str << std::endl;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出量

File(ifstream) : 41 42 43 EA B0 80 EB 82 98 EB 8B A4
ABC????
String literal : 41 42 43 B0 A1 B3 AA B4 D9
ABC???
Run Code Online (Sandbox Code Playgroud)

输出表明字符在字符串文字和文件中的编码方式不同。

据我所知,在c ++中,char字符串是以UTF-8编码的,因此我们可以通过printf或看到它们cout。因此,他们的字节本来应该是相同的,但实际上却是不同的...

有什么办法使用读取UTF-8文本文件std::ifstream吗?


我使用std::wifstream以下文章成功解析xml文件。

但是我正在使用的大多数库仅支持const char*字符串,因此我正在寻找另一种使用方法std::ifstream

而且我也读过这篇文章说不要使用wchar_t。将char字符串视为多字节字符就足够了。

小智 3

使用 UTF-8 编码“ABC\xea\xb0\x80\xeb\x82\x98\xeb\x8b\xa4”应该会给你

\n\n
"\\x41\\x42\\x43\\xEA\\xB0\\x80\\xEB\\x82\\x98\\xEB\\x8B\\xA4"\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以你得到的文件内容是正确的。问题出在您的源文件编码上。不允许在字符串文字中使用非 ASCII 符号,您应该在它们前面加上 u8 来获取 UTF-8 文字:

\n\n
u8"ABC\xea\xb0\x80\xeb\x82\x98\xeb\x8b\xa4"\n
Run Code Online (Sandbox Code Playgroud)\n\n

此时我假设您使用的是 Windows,否则您不会遇到任何编码问题。您必须将终端字符集更改为 UTF-8:

\n\n
chcp 65001\n
Run Code Online (Sandbox Code Playgroud)\n\n

在您的情况下,您正在将 UTF-8 文本从文件读取为字符串,然后将其打印到非 unicode 终端,该终端无法按您的预期显示它。当您打印字符串文字时,您正在打印非 unicode 序列,但此序列编码与您的终端编码匹配,因此您可以看到您所期望的内容。

\n\n

PS:我使用https://mothereff.in/utf-8来获取十六进制字符串的 UTF-8 表示形式。

\n