Как преобразовать строку из CP-1251 в UTF-8? - PullRequest
23 голосов
/ 26 сентября 2011

Я использую мутаген для преобразования данных тегов ID3 ​​из CP-1251 / CP-1252 в UTF-8. В Linux нет проблем. Но в Windows вызов SetValue() для wx.TextCtrl приводит к ошибке:

UnicodeDecodeError: кодек «ascii» не может декодировать байт 0xc3 в позиции 0: порядковый номер не в диапазоне (128)

Исходная строка (предположительно в кодировке CP-1251), которую я извлекаю из мутаген :

u'\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3'

Я пытался преобразовать это в UTF-8:

dd = d.decode('utf-8')

... и даже изменение кодировки по умолчанию с ASCII на UTF-8:

sys.setdefaultencoding('utf-8')

... Но я получаю ту же ошибку.

Ответы [ 6 ]

25 голосов
/ 26 сентября 2011

Если вы точно знаете, что у вас на входе cp1251, вы можете сделать

d.decode('cp1251').encode('utf8')
5 голосов
/ 28 сентября 2011

Ваша строка d является строкой Unicode, не строкой в ​​кодировке UTF-8!Таким образом, вы не можете decode() это, вы должны encode() это в UTF-8 или любую другую кодировку, которая вам нужна.

>>> d = u'\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3'
>>> d
u'\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3'
>>> print d
Áåëàÿ ÿáëûíÿ ãðîìó
>>> a.encode("utf-8")
'\xc3\x81\xc3\xa5\xc3\xab\xc3\xa0\xc3\xbf \xc3\xbf\xc3\xa1\xc3\xab\xc3\xbb\xc3\xad\xc3\xbf \xc3\xa3\xc3\xb0\xc3\xae\xc3\xac\xc3\xb3'

(это то, что вы будете делать в самом конце всей обработкинапример, когда вам нужно сохранить его как файл в кодировке UTF-8).

Если ваш ввод в другой кодировке, то все наоборот:

>>> d = "Schoßhündchen"                 # native encoding: cp850
>>> d = "Schoßhündchen".decode("cp850") # decode from Windows codepage
>>> d                                   # into a Unicode string (now work with this!)
u'Scho\xdfh\xfcndchen'
>>> print d                             # it displays correctly if your shell knows the glyphs
Schoßhündchen
>>> d.encode("utf-8")                   # before output, convert to UTF-8
'Scho\xc3\x9fh\xc3\xbcndchen'
4 голосов
/ 26 сентября 2011

Если d является правильной строкой Unicode, то d.encode('utf-8') возвращает закодированную строку UTF-8.Не проверяйте его, печатая, хотя, возможно, он просто не отображается должным образом из-за shenanigans кодовой страницы.

0 голосов
/ 22 июля 2017

Я бы лучше добавил комментарий к ответу Александра Степаненко, но моя репутация пока не позволяет этого. У меня была похожая проблема с преобразованием тегов MP3 из CP-1251 в UTF-8, и решение кодировать / декодировать / кодировать работало для меня. За исключением того, что мне пришлось заменить первую кодировку на «latin-1», которая по существу преобразует строку Unicode в последовательность байтов без реальной кодировки:

print text.encode("latin-1").decode('cp1251').encode('utf8')

и для сохранения с использованием, например, мутагена его не нужно кодировать:

audio["title"] = title.encode("latin-1").decode('cp1251')
0 голосов
/ 26 октября 2016

Я потерял половину дня, чтобы найти правильный ответ.Поэтому, если вы получили какую-то строку Юникода из внешнего источника в кодировке Windows-1251 (с веб-сайта в моей ситуации), вы увидите в консоли Linux что-то вроде этого:

u '\ u043a \ u043e \ u043c \ u043d \ u0430\ u044d \ u0430 \ u044f \ u0432 \ u0430 \ u0438 \ u0440 \ u0440 ..... '

Это неверное представление ваших данных в Юникоде.Итак, Тим Пицкер прав.Вы должны кодировать () сначала его, затем декодировать (), а затем кодировать снова, чтобы исправить кодировку.

Так что в моем случае эта странная строка была сохранена в переменной "text", а строка:

print text.encode("cp1251").decode('cp1251').encode('utf8')   

дала мне:

"Своя 2-х комнатная квартира сотличным ремонтом .... "

Да, это меня тоже сводит с ума.Но это работает!

PS Сохранение в файл вы должны сделать так же.

some_file.write(text.encode("cp1251").decode('cp1251').encode('utf8'))
0 голосов
/ 07 января 2016

Я предоставил некоторую соответствующую информацию о кодировании / декодировании текста в этом ответе: https://stackoverflow.com/a/34662963/2957811

Чтобы добавить к этому здесь, важно думать о тексте в одном из двух возможных состояний: «закодировано» и «декодированный '

' декодированный 'означает, что он находится во внутреннем представлении вашего интерпретатора / библиотеки, который может использоваться для манипулирования символами (например, поиска, преобразования регистра, среза подстроки, количества символов, ...) или отображения (поиск кодовой точки в шрифте и рисование глифа), но не может быть передан в или из запущенного процесса.

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

Если вы раньше работали с сериализованными объектами, считайте «декодированный» полезным объектом в памяти, а «закодированный» - сериализованной версией.

'\xc1\xe5\xeb\xe0\xff \xff\xe1\xeb\xfb\xed\xff \xe3\xf0\xee\xec\xf3' - это ваша закодированная (или сериализованная) версия, предположительно закодированная с помощью cp1251.Эта кодировка должна быть правильной, потому что это «язык», используемый для сериализации символов и необходимый для воссоздания символов в памяти.

Вам необходимо , чтобы декодировать это из текущей кодировки (cp1251) в символы юникода python, затем перекодируйте его как поток байтов utf8.Ответчик, предположивший d.decode('cp1251').encode('utf8'), имел это право, я просто надеюсь помочь объяснить, почему это должно сработать.

...