代码之家  ›  专栏  ›  技术社区  ›  Cyril N.

与utf-16编码/解码斗争

  •  5
  • Cyril N.  · 技术社区  · 6 年前

    我有一个包含以下内容的字节字符串:

    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的物料清单, 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')
    #> 뻃뿃㐀㐀 ㌀㘀㘀 㘀ⴀ㄀  ㌀㠀 㘀㈀㈀㠀㔀
    

    print(my_var.decode('utf-16be')
    #> 쎾쎿44036606-10038062285
    

    (bom表未删除)

    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)
    

    2 回复  |  直到 6 年前
        1
  •  1
  •   Hyarus    6 年前

    这是正确的 CP1252 编码。

    区别如下:

    你的第一个字节是0x ,二进制为11000011。

    • UTF-8型 :

    前两位被设置,表示UTF-8字符长度为2字节。 得到 0xC3 0xBE 你的第一个角色,也就是UTF-8。

    对于0xC3。

    UTF-16LE 对于Windows。

    添加原始源后编辑

    OPs解决方案:

    bytes(int(value, base=8))
    
        2
  •  0
  •   Cyril N.    6 年前

    根据@Tomalak和@Hyarus的要求,我的问题的原因如下:

    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-8(duh)编码的。所以正确的代码应该是:

    def decode_8bit(cls, match):
        value = match.group().replace(b'\\', b'')
        return bytes(int(value, base=8))
    
    my_var = re.sub(b'\\\\[0-9]{1,3}', decode_8bit, source)
    

    希望能帮助别人。。。祝你编码好运!:/