【发布时间】:2019-02-25 12:53:38
【问题描述】:
我正在解析一个包含一些 UTF-16 编码字符串的文档。
我有一个包含以下内容的字节字符串:
my_var = b'\xc3\xbe\xc3\xbf\x004\x004\x000\x003\x006\x006\x000\x006\x00-\x001\x000\x000\x003\x008\x000\x006\x002\x002\x008\x005'
转换为 utf-8 时,我得到以下输出:
print(my_var.decode('utf-8'))
#> þÿ44036606-10038062285
前两个字符 þÿ 表示它是 UTF-16BE 的 BOM,as indicated on Wikipedia
但是,我不明白的是,如果我像这样尝试 UTF16 BOM:
if value.startswith(codecs.BOM_UTF16_BE)
这返回错误。事实上,打印codecs.BOM_UTF16_BE 并不会显示相同的结果:
print(codecs.BOM_UTF16_BE)
#> b'\xfe\xff'
为什么会这样?我怀疑高端存在一些问题,但不知道如何解决。
已经有一些关于如何在 Stackoverflow 上解码 UTF-16(如 this one)的内容,他们都说一件事:使用 utf-16 解码,Python 将处理 BOM。
...但这对我不起作用。
print(my_var.decode('utf-16')
#> 뻃뿃㐀㐀 ㌀㘀㘀 㘀ⴀ ㌀㠀 㘀㈀㈀㠀㔀
但使用 UTF-16BE:
print(my_var.decode('utf-16be')
#> 쎾쎿44036606-10038062285
(未删除 bom)
使用 UTF-16LE:
print(my_var.decode('utf-16le')
#> 뻃뿃㐀㐀 ㌀㘀㘀 㘀ⴀ ㌀㠀 㘀㈀㈀㠀㔀
因此,出于某种我无法解释的原因,仅使用 .decode('UTF-16') 对我不起作用。为什么?
更新
原始源字符串不是我提到的那个,而是这个:
source = '\376\377\0004\0004\0000\0003\0006\0006\0000\0006\000-\0001\0000\0000\0003\0008\0000\0006\0002\0002\0008\0005'
我使用以下方法对其进行了转换:
def decode_8bit(cls, match):
value = match.group().replace(b'\\', b'')
return chr(int(value, base=8)).encode('utf-8')
my_var = re.sub(b'\\\\[0-9]{1,3}', decode_8bit, source)
也许我在这里做错了什么?
【问题讨论】:
-
UTF-16 BOM 为 0xFE 0xFF。您的输入还有其他内容。可能相关stackoverflow.com/questions/11546351/…
-
您提供的二进制序列不是有效的 UTF-16。检查
print(...)的结果不是检查编码的有效方法,因为print可能不会打印某些字符,所以你不应该相信它。 -
@Tomalak,我已经更新了我的问题(最后)。我忘了提到原始来源,也许它改变了一切?