首页 > 解决方案 > 为什么相同的字符有不同的字节表示以及如何转换

问题描述

$ printf ボ | hexdump 
0000000 e3 83 9c                                       
0000003
$ printf ボ | hexdump 
0000000 e3 83 9b e3 82 99                              
0000006

^ 在 Mac OS 终端下输出。

从文件名中提取 6 字节(我看到有人说 mac 文件名编码问题,不太确定)

另一种是从 xml 文件内容中提取的(XML 1.0 文档文本,UTF-8 Unicode 文本)。

我试图从 xml 文件中 grep 文件名,我猜 ^ 是导致它的原因。

我试图将每个文件放在单独的文件中,希望它可以告诉我编码不同,但都显示为UTF-8 Unicode text

我的问题是这是如何发生的以及如何将 6 字节一转换为 3 字节一。

标签: bashmacosunicodeencodingutf-8

解决方案


请参阅Unicode 规范化形式

较短的版本是由以 UTF-8 编码的单个 Unicode 代码点组成的规范组合形式。Python 示例:

>>> import unicodedata as ud
>>> bytes.fromhex('e3 83 9c').decode('utf8')
'ボ'
>>> ud.name(bytes.fromhex('e3 83 9c').decode('utf8'))
'KATAKANA LETTER BO'

较长的版本是由字母和组合标记组成的规范分解形式:

>>> import unicodedata as ud
>>> s=bytes.fromhex('e3 83 9b e3 82 99 ').decode('utf8')
>>> s
'ボ'
>>> ud.name(s[0])
'KATAKANA LETTER HO'
>>> ud.name(s[1])
'COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK'

在 Python 中,您可以通过以下方式在两种形式之间进行转换:

>>> import unicodedata as ud
>>> ud.normalize('NFD','ボ').encode('utf8').hex(sep=' ')
'e3 83 9b e3 82 99'
>>> ud.normalize('NFC','ボ').encode('utf8').hex(sep=' ')
'e3 83 9c'

推荐阅读