我一直在阅读很多资料,但我仍然对如何计算它感到困惑。我正在做一个练习,询问:
以下哪个位序列(以十六进制数字表示)代表有效的 UFT-8 字符串,如果它们是有效的 UTF-8 字符串,那么位序列对应多少个代码?
0x30c0 0x303C 0xE0ADAA 0x3AA
第一个定义:UTF-8将 Unicode 代码点编码为 1 到 6 个字节的序列。
0x30C0 使用十六进制表示 2 个字节。假设字节序列中首先出现的高位字节,这相当于 0x30 后跟 0xC0。你可以用 Python 3 来写:
>>> seq = b"\x30\xC0"
>>> seq
b'0\xc0'
假设这可能是一个 UTF-8 编码的字节流,我们可以尝试以下decode
方法:
>>> seq.decode("UTF-8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc0 in position 1: invalid start byte
???不工作。该序列不是正确的 UTF-8。
让我们对下一个序列做同样的事情:
>>> seq = b"\x30\x3C"
>>> seq.decode("UTF-8")
'0<'
啊啊!没有例外。这是对应于 2 个代码点的字符串的正确 UTF-8 0<
。
第三个很有趣:
>>> seq = b"\xE0\xAD\xAA"
>>> seq.decode("UTF-8")
'୪'
>>> len(seq.decode("UTF-8"))
1
这 3 个字节仅用于编码一个代码点。但这是哪个字符……嗯……“代码点”?Python 具有以下ord
功能:
>>> ord(seq.decode("UTF-8"))
2922
代码点 2922(十进制)。那是十六进制...
>>> "{:04X}".format( ord(seq.decode("UTF-8")) )
'0B6A'
所以字节序列0xE0 0xAD 0xAA
编码为 UTF-8 的 unicode 代码点U+0B6A
。但那是哪个角色?Python 嵌入了一个模块来查询 Unicode 数据库:
>>> import unicodedata
>>> unicodedata.name( seq.decode("UTF-8") )
'ORIYA DIGIT FOUR'
就是这样:这是奥里亚语书写系统中数字 4对应的代码点。
这个问题提出的非常糟糕。这些都是数字,而不是字符串。我怀疑这意味着表示字节序列,在这种情况下,他们应该将其写为:
0x30 0xc0
0x30 0x3C
0xE0 0xAD 0xAA
0x03 0xAA
...或类似的东西。
如果这实际上是问题的意思(不清楚),那么可以通过简单的检查来看出哪些是无效的 UTF-8:
0xc0
永远不是有效的 UTF-8。0xaa
,但没有有效的多字节序列的第一个字节。或者,你可以试着让计算机解码它们,它会给你一个错误的错误。例如,使用 Python 版本 3,
>>> bytes([0x30,0xc0]).decode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc0 in position 1: invalid start byte
>>> bytes([0x30,0x3c]).decode('utf-8')
'0<'
>>> bytes([0xe0,0xad,0xaa]).decode('utf-8')
'୪'
>>> bytes([0x03,0xaa]).decode('utf-8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xaa in position 1: invalid start byte
>>>