Dd *_* Pp 5 python encoding ucs2 utf-8 endianness
我you
以三种不同的形式编辑三个文件,其中包含相同的内容"你"(英文) - gbk\utf-8\ucs-2,gedit名为"ok1,ok2,ok3".
>>> f1 = open('ok1', 'rb').read()
>>> f2 = open('ok2', 'rb').read()
>>> f3 = open('ok3', 'rb').read()
>>> f1
'\xc4\xe3\n'
>>> f2
'\xe4\xbd\xa0\n'
>>> f3
'`O\n\x00'
>>> hex(ord("`"))
'0x60'
>>> hex(ord("O"))
'0x4f'
Run Code Online (Sandbox Code Playgroud)
事实上f3是'\ x60\x4f',但以下输出让我很困惑
>>> '\xe4\xbd\xa0'.decode("utf-8")
u'\u4f60'
>>> '\xc4\xe3'.decode("gbk")
u'\u4f60'
>>>
Run Code Online (Sandbox Code Playgroud)
为什么只有在ucs-2(或说unicode)中存在endian问题,而不是在utf-8中,而不是在gbk中?
UTF-8和GBK以字节序列存储数据.强烈定义了在这些编码之后的字节值.该字节顺序不随编码,传输或解码中使用的架构而改变.
另一方面,UCS-2或新的UTF-16以2字节的顺序存储数据.这些2字节令牌中的单个字节的顺序是字节序,它取决于底层机器架构.系统必须就如何在与UCS-2中编码的数据进行通信之前识别令牌的字节顺序达成一致.
在您的情况下,Unicode点U + 4F60在UCS-2中编码为单个2字节令牌0x4F60
.由于您的机器将最低有效字节放在内存对齐中最重要的字节之前,因此序列('0x60', '0x4F')
已放入文件中.因此,文件读取将按此顺序生成字节.
Python仍然可以正确解码这些数据,因为它会在形成2字节令牌之前以正确的顺序读取字节:
>>> '`O\n\x00'.decode('utf-16')
u'\u4f60\n'
Run Code Online (Sandbox Code Playgroud)
Endian-ness 仅适用于多字节字,但 UTF-8 使用 8 位单位来编码信息(这就是名称中的 8 所代表的含义)。从来没有在那里订购混淆的问题。
有时可能需要多个单元来编码信息,但它们被认为是不同的。例如,字母A
是一个字节0x41
。当它必须用更多字节编码一个字符时,它使用一个前导指示字节,然后是额外的继续字节来捕获该字符所需的所有信息。从逻辑上讲,这些是不同的单位。
GBK 使用了类似的方案;字符使用 1 个字节为单位,就像 UTF-8 一样,第二个字节可以用于某些字符。
另一方面,UCS-2(及其后继者 UTF-16)是一种 2 字节格式。它以 16 位为单位对信息进行编码,并且这 16 位总是在一起。该单元中的 2 个字节在逻辑上属于一起,现代架构将它们视为一个单元,因此决定了它们的存储顺序。这就是字节序的用武之地,一个单元中 2 个字节的顺序取决于体系结构。在您的体系结构中,字节使用小字节序排列,这意味着“较小”的字节在前。这就是为什么0x4F
字节出现在0x60
文件中的字节之前。
请注意,python 可以很好地读取大端或小端 UTF-16;如果开头没有指示符(字节顺序标记或 BOM),您可以明确选择字节顺序:
>>> '`O\n\x00'.decode('utf-16')
u'\u4f60\n'
>>> '`O\n\x00'.decode('utf-16-le')
u'\u4f60\n'
>>> 'O`\x00\n'.decode('utf-16-be')
u'\u4f60\n'
Run Code Online (Sandbox Code Playgroud)
在后一个例子中,字节被反转,并被解码为大端。
归档时间: |
|
查看次数: |
2292 次 |
最近记录: |