Как понять смысл плохо закодированного сообщения? - PullRequest
10 голосов
/ 28 ноября 2010
---------------------------
ƒGƒ‰[
---------------------------
ƒfƒBƒXƒvƒŒƒCƒ‚[ƒh‚ªÝ’è‚Å‚«‚Ü‚¹‚ñ.
---------------------------
OK   
---------------------------

Я получаю это четкое сообщение об ошибке из Система уединения стрелка 4 , после того, как я его кормлю эта версия 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 в любом случае (ОС, которую я пытался использовать.)


Не совсем так.

Возможно, Каби о чем-то говорит, но это еще не все.Во-первых, я не могу воспроизвести его кодировку:

>>> 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")
ディスプレイモ[ドがン定できません.

Это мусор для Google Translate, однако.Затем я попытался удалить некоторые кусочки.Учитывая, что デ ィ ス プ レ イ означает «отображение», если я удалил «мусор» вокруг битов, которые не могут быть декодированы, я получу:

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

Однако, поскольку я спросил об SO, это не полная история. Что с теми байтами, которые не могут быть декодированы?Как бы вы получили эти байты для начала.

Ответы [ 3 ]

6 голосов
/ 29 ноября 2010

=== файл 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'

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

Переводчик Google: Вы можете установить режим отображения.

Microsoft (Bing) Translate: режим отображения не установлен.

Обновление Немного больше объяснений о том, зачем нужна таблица перевода и почему она сопоставляет \x81 и т. Д. С U + 0081, из статьи Википедии на cp1252 :

Согласно информации на Microsoft и Unicode Сайты Консорциума, позиции 81, 8D, 8F, 90 и 9D не используются. тем не мение вызов API Windows для преобразования из кодовых страниц в Unicode отображает эти к соответствующим кодам управления C1.

6 голосов
/ 28 ноября 2010

Очевидно.

Так как это японская игра

デ ィ ス プ レ イ モ \ x81 [ド が \ x90 ン 定 で き ま せ ん. \ П '

'Disupureimo \ x81 [приложения de \ x90 не могут быть исправлены. \ N '

Поскольку я вставил строку, некоторые отсутствуют.

Кодировка по имени Shift-JIS. Я использую свою Opera, чтобы показать персонажей на самом деле.

EDIT: К сожалению, все мои браузеры не могут добавлять комментарии на SO. Я думаю, это о сети. Поэтому я должен обновить здесь.

Вам, вероятно, следует установить режим отображения на 256 цветов. Это много японской игры нужно.

EDIT2: Интересная история.

О том, как я получил строку, что является самой забавной вещью, я не напрямую закодировал в нее оригинальные байты, как вы, возможно, пытались, только получил:

ニ 断 ニ 達 ニ 湛 ニ 致 ニ 椎 槌 辰 ニ 停 堋 ー ニ 檀 窶 堋 ェ ツ 静 昶 凖 ィ 窶 堙 堋 ォ 窶 堙 懌 堋 ケ 窶 堙 ア.

Но вставив строку на другую веб-страницу в качестве источника, затем с помощью Opera изменил кодировку на Shift-JIS.

Opera имеет эту функцию, которая позволяет вам изменять исходный код веб-страницы и показывать его. Поэтому я написал страницу вроде:

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

и вот что я получил:

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

Что еще более бессмысленно. А вы пробовали изменить цветовой режим на 256 цветов?

3 голосов
/ 29 ноября 2010

Может быть, это поможет:

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.

Редактировать

Опираясь на ответ Джона Мачина:

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

Вывод

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