如何解析似乎混合使用 Unicode 代码点和十六进制值作为字符串的二进制文件?
How can I parse a binary file that seems to use a mix of Unicode Code Points and Hex values for strings?
我有一个包含文本的二进制文件。我需要获取字符串的十六进制字节,并将它们转换为可读文本。我正在使用 Python 3.
编码似乎是 UTF-8,但我在解码某些特定字符串时遇到了一些问题。你看,一些字符串似乎有 unicode 代码点来表示字符,而其他字符串使用它们的十六进制值对应于它们在 UTF-8 字符 table 中的条目。这是一个例子:
4D 6F 6A 65 20 53 70 6F 72 65 20 76 FD 74 76 6F 72 79 -> Moje Spore výtvory
该字符串中的 FD
字节表示 ý
字符,但是如果我们检查字符 table 中的 Unicode 代码点,则 FD 仅对应于此字符,如下所示:
你可以看到,要用十六进制表示这个字符,你需要两个字节。如果所有字符串都像这样,这将不是问题,但其他一些字符串实际上使用十六进制值来表示字符,如下所示:
4C 45 47 4F C2 AE -> LEGO®
在此示例中,两个字节 C2 AE
表示 ®
字符。然而,这是它们的十六进制表示,而不是此处看到的 Unicode 代码点:
问题来了。我无法判断字符串何时使用 Unicode 代码点以及何时使用十六进制值,我需要对其进行完美解析。关于为什么会这样的任何想法?如果我尝试使用 UTF-8 对其进行解码,Python 会崩溃,因为当它达到 FD
这样的值时,它不知道该怎么做。我尝试使用 ord()
和 chr()
函数逐字节解码,但是虽然这可以防止崩溃,但它会使 multi-byte 字符具有不属于的额外内容(例如,乐高示例如下所示:LEGO®
)。数据需要被完美解析,因为它必须被用来产生校验和,所以即使是不可见的东西也会改变结果。谢谢。
第一个字符串(带 FD)不是 UTF-8 编码。可能是 ISO-8859-1 或 Windows-1252。表示 ý
的字节恰好与 Unicode 代码点值匹配,但它不是使用“[U]nicode 代码点来表示字符”。
LEGO 字符串采用 UTF-8 编码。如果您正在从文件中破解字符串并且没有规范,那么您只需要猜测即可。 UTF-8 必须遵循其多字节编码的特定规则,因此如果您首先尝试使用 UTF-8 而不是 UTF-8,则解码很可能会失败。然后您可以回退到 ISO-8859-1
。后者将解码任何内容,即使它不是那种编码。你可能会得到垃圾。
UTF-8 编码示例:
>>> s='Moje Spore výtvory'.encode('utf8')
>>> s
b'Moje Spore v\xc3\xbdtvory'
>>> s.hex()
'4d6f6a652053706f72652076c3bd74766f7279'
>>> s.decode('utf8')
'Moje Spore výtvory'
>>> s.decode('iso-8859-1') # note it works, but garbage
'Moje Spore výtvory'
如果字符串是 ISO-8859-1 编码的:
>>> s='Moje Spore výtvory'.encode('latin1') # an alias for ISO-8859-1
>>> s.hex()
'4d6f6a652053706f72652076fd74766f7279'
>>> s.decode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfd in position 12: invalid start byte
>>> s.decode('latin1')
'Moje Spore výtvory'
我有一个包含文本的二进制文件。我需要获取字符串的十六进制字节,并将它们转换为可读文本。我正在使用 Python 3.
编码似乎是 UTF-8,但我在解码某些特定字符串时遇到了一些问题。你看,一些字符串似乎有 unicode 代码点来表示字符,而其他字符串使用它们的十六进制值对应于它们在 UTF-8 字符 table 中的条目。这是一个例子:
4D 6F 6A 65 20 53 70 6F 72 65 20 76 FD 74 76 6F 72 79 -> Moje Spore výtvory
该字符串中的 FD
字节表示 ý
字符,但是如果我们检查字符 table 中的 Unicode 代码点,则 FD 仅对应于此字符,如下所示:
你可以看到,要用十六进制表示这个字符,你需要两个字节。如果所有字符串都像这样,这将不是问题,但其他一些字符串实际上使用十六进制值来表示字符,如下所示:
4C 45 47 4F C2 AE -> LEGO®
在此示例中,两个字节 C2 AE
表示 ®
字符。然而,这是它们的十六进制表示,而不是此处看到的 Unicode 代码点:
问题来了。我无法判断字符串何时使用 Unicode 代码点以及何时使用十六进制值,我需要对其进行完美解析。关于为什么会这样的任何想法?如果我尝试使用 UTF-8 对其进行解码,Python 会崩溃,因为当它达到 FD
这样的值时,它不知道该怎么做。我尝试使用 ord()
和 chr()
函数逐字节解码,但是虽然这可以防止崩溃,但它会使 multi-byte 字符具有不属于的额外内容(例如,乐高示例如下所示:LEGO®
)。数据需要被完美解析,因为它必须被用来产生校验和,所以即使是不可见的东西也会改变结果。谢谢。
第一个字符串(带 FD)不是 UTF-8 编码。可能是 ISO-8859-1 或 Windows-1252。表示 ý
的字节恰好与 Unicode 代码点值匹配,但它不是使用“[U]nicode 代码点来表示字符”。
LEGO 字符串采用 UTF-8 编码。如果您正在从文件中破解字符串并且没有规范,那么您只需要猜测即可。 UTF-8 必须遵循其多字节编码的特定规则,因此如果您首先尝试使用 UTF-8 而不是 UTF-8,则解码很可能会失败。然后您可以回退到 ISO-8859-1
。后者将解码任何内容,即使它不是那种编码。你可能会得到垃圾。
UTF-8 编码示例:
>>> s='Moje Spore výtvory'.encode('utf8')
>>> s
b'Moje Spore v\xc3\xbdtvory'
>>> s.hex()
'4d6f6a652053706f72652076c3bd74766f7279'
>>> s.decode('utf8')
'Moje Spore výtvory'
>>> s.decode('iso-8859-1') # note it works, but garbage
'Moje Spore výtvory'
如果字符串是 ISO-8859-1 编码的:
>>> s='Moje Spore výtvory'.encode('latin1') # an alias for ISO-8859-1
>>> s.hex()
'4d6f6a652053706f72652076fd74766f7279'
>>> s.decode('utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xfd in position 12: invalid start byte
>>> s.decode('latin1')
'Moje Spore výtvory'