【问题标题】:How to make a filestream read in UTF-8 C++如何在 UTF-8 C++ 中读取文件流
【发布时间】:2018-05-29 15:37:23
【问题描述】:

通过在终端上重定向输入和输出,然后使用 wcin 和 wcout,我能够成功读取 UTF8 字符文本文件

_setmode(_fileno(stdout), _O_U8TEXT);
_setmode(_fileno(stdin), _O_U8TEXT);

现在我希望能够使用文件流读取 UTF8 文本,但我不知道如何设置文件流的模式,以便它可以像使用标准输入和标准输出那样读取这些字符。我已经尝试过使用 wifstreams/wofstreams 并且它们仍然可以自己读写垃圾。

【问题讨论】:

  • 如果您想在您的程序中使用utf-8,您可以使用std::ifstream(或std::cin)读取utf-8,无需调整。当您想在程序中使用 不同的 编码时,问题就来了。然后一些转换是必要的。那么您要将utf-8 转换成的target 编码是什么?
  • 研究数字的数字——在 torah 中寻找模式和信息的“研究”,显然可以找到所有问题的答案。

标签: c++ windows unicode utf-8 filestream


【解决方案1】:

C++ 的<iostreams> 库没有对从一种文本编码到另一种文本编码的转换的内置支持。如果您需要将输入文本从 utf-8 转换为另一种格式(例如,编码的底层代码点),则需要手动编写该转换。

std::string data;
std::ifstream in("utf8.txt");
in.seekg(0, std::ios::end);
auto size = in.tellg();
in.seekg(0, std::ios::beg);
data.resize(size);
in.read(data.data(), size);
//data now contains the entire contents of the file

uint32_t partial_codepoint = 0;
unsigned num_of_bytes = 0;
std::vector<uint32_t> codepoints;
for(char c : data) {
    uint8_t byte = uint8_t(c);
    if(byte < 128) {
        //Character is just a basic ascii character, so we'll just set that as the codepoint value
        codepoints.push_back(byte);
        if(num_of_bytes > 0) {
            //Data was malformed: error handling?
            //Codepoint abruptly ended
        }
    } else {
        //Character is part of multi-byte encoding
        if(partial_codepoint) {
            //We've already begun storing the codepoint
            if((byte >> 6) != 0b10) {
                //Data was malformed: error handling?
                //Codepoint abruptly ended
            }
            partial_codepoint = (partial_codepoint << 6) | (0b0011'1111 & byte);
            num_of_bytes--;
            if(num_of_bytes == 0) {
                codepoints.emplace_back(partial_codepoint);
                partial_codepoint = 0;
            }
        } else {
            //Beginning of new codepoint
            if((byte >> 6) == 0b10) {
                //Data was malformed: error handling?
                //Codepoint did not have proper beginning
            }
            while(byte & 0b1000'0000) {
                num_of_bytes++;
                byte = byte << 1;
            }
            partial_codepoint = byte >> num_of_bytes;
        }
    }
}

此代码将可靠地从 [正确编码] utf-8 转换为 utf-32,这通常是直接转换为字形 + 字符的最简单形式,但请记住 codepoints are not characters

为了使您的代码保持一致,我的建议是使用 std::string 将 utf-8 编码文本存储在您的程序中,并将 utf-32 编码文本存储为 std::vector&lt;uint32_t&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-27
    • 2019-01-03
    相关资源
    最近更新 更多