2016-12-12 3 views
1

У меня есть текстовый набор данных, который имеет некоторые проблемы с кодировкой. Автор поручил сделать:Python, понимающий преобразование Unicode

for line in fpointer: 
    line.encode('latin-1').decode('utf-8') 

Для устранения проблем.

Я хотел понять, почему это было необходимо, я открыл файл перед закреплением и увидел эту строку:

103 But in Imax 3-D , the clichés disappear into the vertiginous perspectives opened up by the photography . 

После преобразования она стала:

103 But in Imax 3-D , the clichés disappear into the vertiginous perspectives opened up by the photography . 

Это имеет смысл.

Но я не мог понять, что могло бы привести к исходной проблеме и как это исправить?

Я передал ссылку юникода питона: https://docs.python.org/3/howto/unicode.html

Я также проверил символы и их значения:

Кодирование UTF-8 для é является c3a9 и изо-8859-1 кодировки для c3 является и для © это а9.

Это имеет смысл, но я не могу установить соединение.

Как именно строка хранится в исходном файле и как ее отредактировал фрагмент кода?

+0

Какую версию Python вы используете (Python2 или Python3), и как открывается исходный файл? –

+0

@SergeBallesta Я использую python 3, исходный файл открывается в режиме чтения без указания кодировки. –

ответ

2

Итак, что случилось, так это то, что текст, который вы были «с двойным кодированием», как utf-8.

Итак, в какой-то момент процесса, который генерировал данные, у вас был текст, который уже имел внутреннее представление «\ xc3 \ xa9» для «é», был интерпретирован как находящийся в латинском-1, а re -трансформирован из «latin1» (где «\ xc3 \ xa9» представляет «Ã ©») для utf-8, так что символ ach был расширен до двух байтов, став: «\ xc3 \ x83» «\ xc2 \ xa9 "(utf-8 для" Ã © "). Поскольку @Novoselov помещает это в другой ответ, это, вероятно, привело к тому, что вы открыли файл для чтения в виде текста без указания кодировки в Windows: Python будет считать, что файл «latin-1», стандартная кодировка Windows, и, следовательно, читайте каждый байт там, который является частью текстовой последовательности an-utf-8 как единый латинский символ.

Какое исправление: настройка системы уже настроена на чтение текста как utf-8 - поэтому, когда вы получили строки в цикле for, вы получили строки Python-3 (Юникод Python-2), правильно интерпретированные для UTF -8 символов в текстовом файле. Таким образом, 4-байтовая последовательность стала 2 текстовыми символами. Теперь одна характеристика кодировки «latin1» заключается в том, что она «прозрачна»: она эквивалентна вообще не выполняет никакого преобразования в текстовых байтах. Другими словами, каждый символ, представленный значением, который вписывается в один байт в внутреннем представлении Юникода Python, становится одним байтом в кодированной байтовой строке. (И каждый символ, значение которого не помещается в байте, вообще не может быть закодировано как Latin-1, что приводит к ошибке Unicode-Encode).

Итак, после «прозрачного» шага кодирования у вас есть байты, которые представляют ваш текст - на этот раз с «одним проходом» кодировки utf-8. И декодирование этих байтов как «utf-8» дало вам правильный текст для файла.

снова:

Это был оригинальный текст: "клише". Закодировано в UTF-8, оно выглядит примерно так: b'clich \ xc3 \ xa9 ' Но исходный процесс, создавший ваш файл, считал эту последовательность как находящуюся в латинском-1, поэтому преобразовал как> 0x80 символов в utf- 8: b'clich \ xc3 \ x83 \ xc2 \ xa9 '. И это то, что печатает как "клише"

на чтение, Python3 гласит: b'clich \ xc3 \ x83 \ xc2 \ xA9' с диска, и возвращается к вам "©" clichà как (юникод) текст. Вы кодируете это в байты и получаете b'clich \ xc3 \ xa9 'с вызовом "encode (' latin-1 '). Наконец, вы затем« декодируете », что из« utf-8 »получается текст« cliché »,

Python3 не просто позволяет испортить текст следующим образом. Чтобы перейти от текста к неправильной версии, вы использовали также «прозрачную» кодировку «latin-1» - это пример:

In [10]: a = "cliché" 

In [11]: b = a.encode("utf-8") 

In [12]: b 
Out[12]: b'clich\xc3\xa9' 

In [13]: c = b.decode("latin1").encode("utf-8") 

In [14]: c 
Out[14]: b'clich\xc3\x83\xc2\xa9' 
1

Исходный текст был закодирован в utf-8, но некоторый процесс декодировал его как latin1, а затем снова закодировал его как utf-8.

Чтобы получить исходный текст, вам необходимо отменить этот процесс: вы декодируете текст из файла как utf-8 (это не включено в ваш фрагмент, но, я думаю, вы открываете его с помощью кодировки utf-8), а затем кодируете он как latin1, затем снова декодируется как utf-8.

0

Из вашего комментария, вы говорите, что вы открываете текстовый файл в Python 3 без указания каких-либо кодирования. В этом случае, Python использует системы кодировку, которая Latin1 на Windows.

Этого достаточно, чтобы объяснить, что вы получаете, если файл был оригинальным, закодированным utf8. Но ИМХО правильный способ указать кодировку файла в функции open:

fd = open(filename, encoding='utf8') 

таким образом, вы сразу получите правильные символы без необходимости коррекции кодирования-декодирования.

Смежные вопросы