代码之家  ›  专栏  ›  技术社区  ›  badp

如何理解编码错误的消息?

  •  10
  • badp  · 技术社区  · 14 年前
    ---------------------------
    ƒGƒ‰[
    ---------------------------
    ƒfƒBƒXƒvƒŒƒCƒ‚[ƒh‚ªÝ’è‚Å‚«‚Ü‚¹‚ñ.
    ---------------------------
    OK   
    ---------------------------
    

    我从中得到这个清晰的错误信息 Shooter's Solitude system 4 在我喂它之后 this version of d3drm.dll (叹气)

    为了您的方便,这里有一个Hexdump:

    00000000  c6 92 66 c6 92 42 c6 92  58 c6 92 76 c6 92 c5 92  |..f..B..X..v....|
    00000010  c6 92 43 c6 92 e2 80 9a  c2 81 5b c6 92 68 e2 80  |..C.......[..h..|
    00000020  9a c2 aa c2 90 c3 9d e2  80 99 c3 a8 e2 80 9a c3  |................|
    00000030  85 e2 80 9a c2 ab e2 80  9a c3 9c e2 80 9a c2 b9  |................|
    00000040  e2 80 9a c3 b1 2e 0a                              |.......|
    00000047
    

    如何将其转换为一致的错误消息——也就是说, 您将如何为该错误消息找到正确的编码/解编码对?


    这是我试过的。

    我想问题是开发人员使用了错误的编码设置(考虑到游戏的年龄,这是为WinXP开发的,这是意料之中的)。通过观察它,我们可以推测消息是以某种多字节编码的。( ƒf ƒB ƒX ƒv ƒŒ )

    但是,每个组似乎由三个字节(变量?)。这排除了通常的嫌疑犯:

    >>> wat = "ƒfƒBƒXƒvƒŒƒCƒ‚[ƒh‚ªÝ’è‚Å‚«‚Ü‚¹‚ñ. "
    >>> wat.encode("UTF-8").decode("UTF-32")
    UnicodeDecodeError: 'utf32' codec cannot decode bytes in position 0-3:
    codepoint not in range(0x110000)
    >>> wat.encode("UTF-8").decode("UTF-16")
    UnicodeDecodeError: 'utf16' codec cannot decode bytes in position 70-70:
    truncated data
    >>> wat.encode("UTF-8")[:-1].decode("UTF-16")
    '鋆왦䊒鋆왘皒鋆鋅鋆왃\ue292骀臂왛梒胢슚슪쎐\ue29d馀ꣃ胢쎚\ue285骀ꯂ胢쎚\ue29c骀맂胢쎚⺱'
    #meaningless according to Google Translate.
    

    我选择UTF-8作为起始编码,因为ASCII不起作用( UnicodeEncodeError: 'ascii' codec can't encode character '\u0192' in position 0: ordinal not in range(128) )UTF-8应该是Windows7的默认编码(我尝试使用的操作系统)。


    不完全在那里。

    卡比可能在做什么,但这不是全部。首先,我不能复制他的编码:

    >>> print (wat.encode("UTF-8").decode("Shift-JIS"))
    UnicodeDecodeError: 'shift_jis' codec cannot decode bytes in position 22-23: illegal multibyte sequence
    >>> print (wat.encode("UTF-8")[:22].decode("Shift-JIS"))
    ニ断ニ達ニ湛ニ致ニ椎槌辰ニ停
    

    维基百科说有一个非常相似的编码:CP932。

    >>> print(wat.encode("UTF-8").decode("932"))
    UnicodeDecodeError: 'cp932' codec cannot decode bytes in position 44-45: illegal multibyte sequence
    >>> print(wat.encode("UTF-8")[:44].decode("932"))
    ニ断ニ達ニ湛ニ致ニ椎槌辰ニ停喙ニ檀窶堋ェテ昶凖ィ窶堙
    

    又一次,和他贴的很不一样。不过,让我们看看:

    >>> print("ディスプレイモ\x81[ドが\x90ン定できません.\n")
    ディスプレイモ[ドがン定できません.
    

    不过,这对谷歌翻译来说是垃圾。然后我试着去掉一些碎片。考虑到这意味着“显示”,如果我移除了无法解码的位周围的“垃圾”,我会得到:

      ディスプレイモ\x81[ドが\x90ン定できません.
    → ディスプレイ      ドが    ン定できません.
    → The display mode is not specified.
    

    但是,既然我问了这么多,这不是全部的故事。 那些无法解码的字节是什么?如何从这些字节开始。

    3 回复  |  直到 14 年前
        1
  •  6
  •   John Machin Santi    14 年前

    # start with the OP's hex dump:
    hexbytes = """
    c6 92 66 c6 92 42 c6 92  58 c6 92 76 c6 92 c5 92
    c6 92 43 c6 92 e2 80 9a  c2 81 5b c6 92 68 e2 80
    9a c2 aa c2 90 c3 9d e2  80 99 c3 a8 e2 80 9a c3
    85 e2 80 9a c2 ab e2 80  9a c3 9c e2 80 9a c2 b9
    e2 80 9a c3 b1 2e 0a
    """
    strg = ''.join(
        chr(int(hexbyte, 16))
        for hexbyte in hexbytes.split()
        )
    uc = strg.decode('utf8') # decodes OK but result is gibberish
    uc_hex = ' '.join("%04X" % ord(x) for x in uc)
    print uc_hex
    # but it's stuffed ... U+0192??? oh yeah, 0x83
    badenc = 'cp1252' # sort of, things like 0x81 have to be allowed for
    fix_bad = {}
    for i in xrange(256):
        b = chr(i)
        try:
            fix_bad[ord(b.decode(badenc))] = i
        except UnicodeDecodeError:
            fix_bad[i] = i
    
    recoded = uc.translate(fix_bad).encode('latin1')
    better_uc = recoded.decode('cp932')
    # It's on Windows; cp932 what would have been used
    # but 'sjis' gives the same answer
    better_uc_hex = ' '.join("%04X" % ord(x) for x in better_uc)
    print better_uc_hex
    print repr(better_uc)
    print better_uc
    

    0192 0066 0192 0042 0192 0058 0192 0076 0192 0152 0192 0043 0192 201A 0081 005B 0192 0068 201A 00AA 0090 00DD 2019 00E8 201A 00C5 201A 00AB 201A 00DC 201A 00B9 201A 00F1 002E 000A
    
    30C7 30A3 30B9 30D7 30EC 30A4 30E2 30FC 30C9 304C 8A2D 5B9A 3067 304D 307E 305B 3093 002E 000A
    
    u'\u30c7\u30a3\u30b9\u30d7\u30ec\u30a4\u30e2\u30fc\u30c9\u304c\u8a2d\u5b9a\u3067\u304d\u307e\u305b\u3093.\n'
    
    ディスプレイモードが設定できません.
    

    \x81 Wikipedia article on cp1252

        2
  •  6
  •   Kabie    14 年前

    <!DOCTYPE html>
    <head>
    <title>test</title>
    </head>
    <body>
    'ƒfƒBƒXƒvƒŒƒCƒ‚ƒh‚ªÝ’è‚Å‚«‚Ü‚¹‚ñ.
    </body>
    </html>
    

        3
  •  3
  •   Mark Tolonen    14 年前

    from binascii import unhexlify
    
    data = '''\
    c6 92 66 c6 92 42 c6 92 58 c6 92 76 c6 92 c5 92
    c6 92 43 c6 92 e2 80 9a c2 81 5b c6 92 68 e2 80
    9a c2 aa c2 90 c3 9d e2 80 99 c3 a8 e2 80 9a c3
    85 e2 80 9a c2 ab e2 80 9a c3 9c e2 80 9a c2 b9
    e2 80 9a c3 b1 2e 0a
    '''
    
    data = unhexlify(data.replace(' ','').replace('\n',''))
    print data.decode('utf8').encode('windows-1252','xmlcharrefreplace').decode('shift-jis')
    

    ディスプレイモ&#129;[ドが&#144;ン定できません.
    

    from binascii import unhexlify
    import re
    
    data = '''\
    c6 92 66 c6 92 42 c6 92 58 c6 92 76 c6 92 c5 92
    c6 92 43 c6 92 e2 80 9a c2 81 5b c6 92 68 e2 80
    9a c2 aa c2 90 c3 9d e2 80 99 c3 a8 e2 80 9a c3
    85 e2 80 9a c2 ab e2 80 9a c3 9c e2 80 9a c2 b9
    e2 80 9a c3 b1 2e 0a
    '''
    
    data = unhexlify(data.replace(' ','').replace('\n',''))
    data = data.decode('utf8').encode('windows-1252','xmlcharrefreplace')
    # convert the XML entities that windows-1252 couldn't encode back into bytes
    data = re.sub(r'&#(\d+);',lambda x: chr(int(x.group(1))),data)
    print data.decode('shift-jis')
    

    ディスプレイモードが設定できません.