3

以下字节流被标识为 UTF-8,它包含希伯来语句子:דירות לשותפים בתל אביב - הומלס. 我试图理解编码。

ubuntu@ip-10-126-21-104:~$ od -t x1 homeless-title-fromwireshark_followed_by_hexdump.txt
0000000 0a 09 d7 93 d7 99 d7 a8 d7 95 d7 aa 20 d7 9c d7
0000020 a9 d7 95 d7 aa d7 a4 d7 99 d7 9d 20 20 d7 91 d7
0000040 aa d7 9c 20 d7 90 d7 91 d7 99 d7 91 20 2d 20 d7
0000060 94 d7 95 d7 9e d7 9c d7 a1 0a
0000072
ubuntu@ip-10-126-21-104:~$ file -i homeless-title-fromwireshark_followed_by_hexdump.txt
homeless-title-fromwireshark_followed_by_hexdump.txt: text/plain; charset=utf-8

该文件是 UTF-8,我通过打开记事本(Windows 7)验证了这一点,输入希伯来字符ד,然后保存文件。结果如下:

ubuntu@ip-10-126-21-104:~$ od -t x1 test_from_notepad_utf8_daled.txt
0000000 ef bb bf d7 93
0000005
ubuntu@ip-10-126-21-104:~$ file -i test_from_notepad_utf8_daled.txt
test_from_notepad_utf8_daled.txt: text/plain; charset=utf-8

ef bb bf以 utf-8 形式编码的 BOM 在哪里,并且d7 93正是出现在原始流中的字节序列之后0a 09(新行,ascii 中的制表符)。

这里的问题是,通过 unicode 代码页,ד应该这样编码,05 D3为什么以及如何产生 utf-8 编码d7 93

d7 93在二进制中是11010111 10010011,而
05 D3在二进制中是00000101 11010011

我似乎找不到对这些编码有意义的正确转换,(据我了解)代表相同的 Unicode 实体,即“希伯来字母 DALET”

谢谢你,
马克西姆。

4

3 回答 3

6

Unicode 定义(除其他外)一堆“代码点”,并给每个“代码点”一个数值。的值为HEBREW LETTER DALETU+05D3 或0x05D3。但这只是一个数字,并没有告诉您如何在文件/内存中“编码”代码点(即实际位的集合)...UTF-8(以及 UTF-16、UTF- 32 和各种其他方案)告诉你如何做到这一点。

实际上有一种将 Unicode 代码点转换为 UTF-8 字符的公式化方式(但这是一个完全不同的 SO 问题)。事实证明,在 UTF-8 中,HEBREW LETTER DALET编码为0xD7 0x93. 顺便说一句,如果您找到一个允许您保存为 UTF-32 或 UCS-4 的文本编辑器,您会发现(除了一个非常大的文件)您使用十六进制编辑器看到的字节应该匹配Unicode 规范中的代码点。

页面可能会提供有关该字符的某些表示的一些额外信息。

对于 Unicode 的精彩介绍,我建议 Joel Spolsky 的The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)

于 2011-05-27T14:55:23.717 回答
4

Unicode 代码点 U+0000..U+007F 在 UTF-8 中编码为单个字节 0x00..0x7F。

Unicode 代码点 u+0080..U+07FF(包括 HEBREW LETTER DALET U+05D3)以 UTF-8 编码为两个字节。这些二进制值可以分为一组 5 位和一组 6 位,如 xxxxxyyyyyy。UTF-8 表示的第一个字节的位模式为 110xxxxxx;第二个具有位模式 10yyyyyy。

0x05D3 = 0000 0101 1101 0011 

0x05D3的后6位为010011;以 10 为前缀,表示 1001 0011 或 0x93。前5位为10111;以 110 为前缀,表示 1101 0111 或 0xD7。

因此,U+05D3 的 UTF-8 编码为 0xD7 0x93。

Unicode 代码点 U+0800 向上的规则更多,需要 3 或 4 个(但不是更多)字节用于 UTF-8 表示。连续字节始终具有 10yyyyyy 位模式。第一个字节具有位模式 1110xxxx(3 个字节值)和 11110xxx(4 个字节值)。有许多字节值不能出现在有效的 UTF-8 中;它们是 0xC0、0xC1 和 0xF5..0xFF。

于 2011-05-27T15:46:34.567 回答
2

旧代码页定义了一组字符及其到字节序列的映射。Unicode 将字符集字符编码的概念分开。

因此,Unicode 字符集是一个代码点列表。每个代码点都被分配一个唯一值作为标识符 -ד是 U+05D3。

编码 - Unicode 转换格式 - 描述了如何将每个代码编码为一系列代码单元

UTF-8 使用 1 个八位字节的代码单元,代码点被编码为 1 到 4 个字节的序列。该算法在RFC 3629中进行了描述。

UTF-16 也存在类似的过程,它使用 2 个八位字节的代码单元 - 每个代码点是两个或四个字节。对于 UTF-32,除了使每个值都长四个字节外,没有什么可做的。这些编码可以采用大端或小端形式,因此 U+05D3 可能是UTF-3200 00 05 D3D3 05 00 00UTF-32。BOM 通常用于说明正在使用哪种编码以及如果数据的编码不明确,则字节序是什么。

还有 UTF-7,但我从未在野外见过它。

于 2011-05-27T15:29:38.477 回答