【发布时间】:2022-01-12 23:44:16
【问题描述】:
我有一个 UTF8 文本文件,其中包含 8 位和 24 位 UTF8 编码(ASCII 和日语)。
我的目标是逐个读取字符,然后输出如下内容:
{'V', 0x02},
这是一个C++语言初始化入口,其中第一个参数是UTF8编码,第二个参数是文件内的索引或位置。
我的第一步是成功读取UTF8文本文件并输出到控制台。
这是输入文件的示例:
()+-0123456789Vanoty˄˅いおがきくさしすせただてでなにのびまみむめりるれをん
这是我的程序的输出示例:
$ ./main.exe
Size of wchar_t: 2
32
40
41
43
45
48
49
50
51
52
53
54
55
56
57
86
97
110
111
116
121
4294953604
4294953605
4293034116
4293034122
4293034124
4293034125
4293034127
4293034133
4293034135
4293034137
4293034139
4293034143
4293034144
这是我的代码:
#include <fstream>
#include <iostream>
int main()
{
std::cout << "Size of wchar_t: " << sizeof(wchar_t) << "\n";
std::ifstream japanese_file("japanese_font_glyphs_all_112_qty_horizontal_layout.txt", std::ios::binary);
char c = '\0';
char32_t utf8_char = 0;
while (japanese_file.read(&c, 1))
{
unsigned int bytes_in_encoding = 1u;
if ((c & 0x80u) == 0U)
{
bytes_in_encoding = 1u;
}
else
{
if ((c & 0xF0u) == 0xE0u)
{
bytes_in_encoding = 3u;
}
else
{
if ((c & 0xE0u) == 0xC0u)
{
bytes_in_encoding = 2u;
}
}
}
char32_t utf8_encoding = 0u;
switch (bytes_in_encoding)
{
case 1:
utf8_char = c;
break;
case 2:
{
char c2 = 0;
japanese_file.read(&c2, 1);
utf8_char = (c * 0x100ul) + c2;
}
break;
case 3:
{
char c2 = 0;
japanese_file.read(&c2, 1);
char c3 = 0;
japanese_file.read(&c3, 1);
utf8_char = (c * 0x10000ul) + (c2 * 0x100ul) + c3;
}
break;
default:
break;
}
std::cout << utf8_char << "\n";
}
japanese_file.close();
return EXIT_SUCCESS;
}
输出显示wchar_t的大小为2,不足以容纳日文字形的24位编码。
那么,我应该使用什么代码将 24 位 UTF8 编码(作为单个字形)输出到控制台?
设置:
g++ (GCC) 10.2.0 -- Cygwin
视窗 10
视觉工作室 2017
我正在编写的应用程序将在 Windows 10 上作为控制台应用程序运行。
编辑 1 -- 背景
我的应用程序将生成 C++ 数据语句,用于为显示芯片的位图寄存器创建索引。
这是结构定义和一些示例条目:
struct UTF8_To_Bitmap_Index_t
{
char32_t encoded_character; //!< UTF8 encoding.
uint8_t bitmap_index; //!< Index of glyph within the font.
uint8_t padding_alignment; //!< For alignment purposes, not used.
};
static const
UTF8_To_Bitmap_Index_t default_conversion_table[] =
{
{'¡', 0x01, 0u},
{'À', 0x02, 0u},
{'Á', 0x03, 0u},
{'Ã', 0x04, 0u},
{'Ä', 0x05, 0u},
{'Å', 0x06, 0u},
};
【问题讨论】:
-
呃,两个字节(Windows 上的 wchar_t)对于几乎所有晦涩难懂的日语字符来说已经绰绰有余了。您的 UTF-8 解析错误。为什么不使用图书馆? Windows 已安装 ICU,您可以使用 ICU 库轻松处理所有这些。
-
正确的名称是“UTF-8”。而且每个字符最多可以遇到 4 个字节,而不仅仅是 24 位。
-
@AmigoJack 每个 encoded 字符的字节数无关紧要(我总是接受 CESU-8,但如果你想严格一点,那么 UTF-8 最多为 4八位字节)。每个解码“字符”的字节数各不相同,但如果您的意思是每个代码点,那么它是三个 == 24位。但是,对于 BMP 之外的代码点,您只需要第三个八位字节。 (所有普通的日语代码点都在 BMPinside 中。)因此,如果 OP 坚持使用 BMP,那就没关系了。但如果是这样,由于 Windows 使用 UTF-16,更喜欢使用库进行解码和编码。 ICU 内置在所有 Win OS 中,并且可以很好地处理这一点 - 使用它。
-
@Dúthomhas:BMP 有大约 60000 个字符。两个八位字节的 UTF8 编码具有
110xxxxx 1yyyyyyy的形式,因此根据鸽巢原理,我们可以证明绝大多数 BMP 字符都需要 3 个八位字节的 UTF-8。平假名和片假名很可能是两个八位字节,但仅汉字就太多了,无法放入两个 UTF-8 八位字节。 -
哦,看来我误解了 OP 想要解码 UTF-8 数据的愿望。我不确定他打算如何使用编码值进行字体字形查找,但是,嘿,输出的第一个示例显示了一个 Unicode 代码点,最后一个也是如此。也许OP可以澄清......?
标签: c++ utf-8 visual-studio-2017 windows-10 g++