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

时间:2010-11-28 18:52:27

标签: python language-agnostic windows-7 windows-xp character-encoding

---------------------------
ƒ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应该是Windows 7的默认编码(我尝试使用的操作系统。)


不完全在那里。

Kabie可能会有所作为,但这不是完整的故事。首先,我无法重现他的编码:

>>> 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 个答案:

答案 0 :(得分:6)

显然。

因为这是日本游戏

  

'ディスプレイモ\ X81 [ドが\ X90ン定できません。\ N'

     

'Disupureimo \ x81 [de \ x90应用程序无法修复。 \ N'

因为我粘贴了字符串,所以有一些缺失。

名为Shift-JIS的编码。我用我的Opera实际显示角色。

修改 可悲的是,我的所有浏览器都无法在SO上添加评论。我想这是关于网络的。所以我必须在这里更新。

您可能应将显示模式设置为256色。这需要很多日本游戏。

<强> EDIT2: 有趣的故事。

关于我如何得到字符串,这是最有趣的事情,我不会直接将原始字节编码到其中,正如您可能尝试过的,只有这样:

  

ニ断ニ达ニ湛ニ致ニ椎槌辰ニ停堋ーニ檀窭堋ェツ静昶凖ィ窭堙堋ォ窭堙怿堋ケ窭堙ア

但是将字符串粘贴到另一个网页作为源代码,然后使用Opera将编码更改为Shift-JIS。

Opera具有此功能,可让您修改网页的源代码并进行显示。所以我写了一个页面:

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

这就是我得到的:

  

“ディスプレイモドがン定できません。

哪个更无意义。您是否尝试将颜色模式更改为256色?

答案 1 :(得分:6)

=== file disupure.py ===

# 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

在IDLE中运行此结果(为清晰起见,添加了空白行):

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'

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

谷歌翻译:您可以设置显示模式。

Microsoft(Bing)翻译:未设置显示模式。

更新更多解释为什么需要转换表,以及为什么它从Wikipedia article on cp1252

\x81等映射到U + 0081
  

根据有关的信息   微软和Unicode   联盟的网站,第81位,   8D,8F,90和9D未使用。然而   用于转换的Windows API调用   从代码页到Unicode映射这些   到相应的C1控制代码。

答案 2 :(得分:3)

也许这会有所帮助:

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;ン定できません.

您提供的十六进制数据是Shift_JIS解码为windows-1252,然后重新编码为UTF-8。

修改

以John Machin的回答为基础:

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')

输出

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