Борьба с кодировкой / декодированием utf-16 - PullRequest
0 голосов
/ 21 сентября 2018

Я анализирую документ, содержащий некоторую строку в кодировке UTF-16.

У меня есть строка байтов, которая содержит следующее:

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, , как указано в Википедии

Но я не понимаю, что если я попробую спецификацию UTF16 следующим образом:

if value.startswith(codecs.BOM_UTF16_BE)

Это возвращает false.На самом деле, печать codecs.BOM_UTF16_BE не дает таких же результатов:

print(codecs.BOM_UTF16_BE)
#> b'\xfe\xff'

Почему это так? Я подозреваю некоторые сопутствующие проблемы на верхнем уровне, но не знаю, как это сделать.исправить это.

Уже есть несколько упоминаний о том, как декодировать UTF-16 в Stackoverflow (например, this ), и все они говорят одно: декодируйте с использованием utf-16 иPython будет обрабатывать спецификацию.

... Но это не работает для меня.

print(my_var.decode('utf-16')
#> 뻃뿃㐀㐀 ㌀㘀㘀 㘀ⴀ㄀  ㌀㠀 㘀㈀㈀㠀㔀

Но с UTF-16BE:

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

(бомба не удалена)

И с UTF-16LE:

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 ]

0 голосов
/ 21 сентября 2018

В соответствии с запросом @Tomalak и @Hyarus, вот причина моей проблемы:

При декодировании 8-битных значений я возвращал их в кодировке UTF-8:

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 (дух).Таким образом, правильный код должен был быть:

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)

Надеюсь, это поможет кому-то еще ... Удачи в кодировании!: /

0 голосов
/ 21 сентября 2018

Правильно, что þÿ указывает на спецификацию для UTF-16BE, если вы используете кодировку CP1252 .

Разница в том,следующее:

Ваш первый байт - 0x C3 , что в двоичном виде 11000011.

  • UTF-8 :

Первые два бита установлены и указывают, что ваш символ UTF-8 имеет длину 2 байта.Получение 0xC3 0xBE для вашего первого символа, которое þ для UTF-8.

  • CP1252

CP1252 всегда1 байт и возвращает Ã для 0xC3.

Но если вы посмотрите 0xC3 в вашем связанном списке спецификации, вы не найдете подходящей кодировки.Похоже, что во-первых не было спецификации.

Вероятно, стоит использовать кодировку по умолчанию, которая UTF-16LE для Windows.

Редактировать после исходного источникадобавлено

Ваша кодировка в UTF-8 уничтожает спецификацию, потому что она не является допустимой UTF-8.Старайтесь избегать декодирования и передавайте список байтов.

OPs решение:

bytes(int(value, base=8))
...