【问题标题】:Interpreting UTF-8 unicode strings in c++在 C++ 中解释 UTF-8 Unicode 字符串
【发布时间】:2021-12-12 07:08:00
【问题描述】:

目前使用 WSL2 Ubuntu、G++ 在 C++20 中编码。

如果我有一个由 utf-8 unicode 字符组成的 .txt 文件:

▄  ▄ ▄▄▄ ▄   ▄   ▄▄▄▄  ▄▄  ▄   ▄ ▄▄▄
  1. 如何获取此 unicode 字符串的长度(unicode 字符数)?

  2. 如何读取文件内容并打印出 unicode 字符串?

【问题讨论】:

  • Unicode 字符实际上并没有说明什么。您必须首先知道或确定文件编码。严格来说 Utf-8 是 unicode,UTF-16LE 是 Unicode,UTF-32 是 Unicode - 所以首先需要回答的真正问题是它是哪个 unicode。因为很可能您必须自己进行转换
  • 如何找出正在使用的编码?
  • 有时文件的前几个字节会告诉你。其他时候,您必须做一些业余加密并尝试所有这些,直到找到有意义的解码消息。
  • 还有ICU library 对文件产生了一些不错的效果。我自己在使用那个库,因为我懒得写一些复杂的东西
  • 我将单个字符的二进制与unicode表进行了比较,看起来它使用的是UTF-8编码。

标签: c++ unicode


【解决方案1】:

假设:

  • stdout 支持 UTF-8(在 Windows 上,您可以在 cmd 提示符下使用 chcp 65001
  • 我们计算的是 Unicode 代码点,而不是由多个代码点组成的字形。

UTF-8 编码由位模式后的起始字节组成:

  1. 0xxxxxxx(单字节编码)
  2. 110xxxxx(两字节编码)
  3. 1110xxxx(三字节编码)
  4. 11110xxx(四字节编码)

后续字节使用10xxxxxx 作为位模式。

可以使用std::string 读取UTF-8 并相应地处理字节。

演示代码:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main() {
    ifstream f("input.txt");
    string s;
    getline(f,s);
    cout << "string: " << s << endl;
    cout << "length(bytes): " << s.length() << endl;

    int codepoints = 0;
    for(auto b : s) {
        if((b & 0xC0) != 0x80) // not UTF-8 intermediate byte?
            ++codepoints;
    }

    cout << "length(code points): " << codepoints << endl;
}

输出:

string: ▄  ▄ ▄▄▄ ▄   ▄   ▄▄▄▄  ▄▄  ▄   ▄ ▄▄▄
length(bytes): 72
length(code points): 36

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-08
    • 2017-03-04
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多