Как я могу понять плохо кодированное сообщение?

---------------------------
ƒGƒ‰[
---------------------------
ƒfƒBƒXƒvƒŒƒCƒ‚[ƒh‚ªÝ’è‚Å‚«‚Ü‚¹‚ñ.
---------------------------
OK   
---------------------------

Я получаю это ясное сообщение об ошибке из Shooter Solitude system 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 (OS, которую я пытался использовать.)


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

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

>>> 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.

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

Ответ 1

=== файл disupure.py ===

# start with the OP 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 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 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 Translate: вы можете установить режим отображения.

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

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

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

Ответ 2

Очевидно.

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

'デ ィ ス プ レ イ モ\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

Возможно, это поможет:

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

Выход

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