11

UnicodeDecodeError: Кодек 'charmap' не может декодировать байт X в позиции Y: символ отображается как <неопределённый>

13

Я пытаюсь сделать некоторые манипуляции с текстовым файлом, заполненным информацией, используя программу на Python 3. Однако при попытке прочитать файл я получаю следующую ошибку:

Traceback (most recent call last):  
  File "LOCATION_OF_SCRIPT", line NUMBER, in <module>  
    text = file.read()
  File "C:\Python31\lib\encodings\cp1252.py", line 23, in decode  
    return codecs.charmap_decode(input,self.errors,decoding_table)[0]
UnicodeDecodeError: 'charmap' codec can't decode byte 0x90 in position 2907500: character maps to <undefined>  

Не могу понять, как исправить эту ошибку. Есть ли какая-то информация о том, как правильно прочитать файл с учетом его кодировки?

5 ответ(ов)

19

Файл, о котором идет речь, не использует кодировку CP1252. Он использует другую кодировку, которую вам придется определить самостоятельно. Наиболее распространенные кодировки — это Latin-1 и UTF-8. Поскольку 0x90 на самом деле ничего не значит в Latin-1, вероятнее всего, это UTF-8 (где 0x90 является байтом продолжения).

Вы можете указать кодировку при открытии файла:

file = open(filename, encoding="utf8")
0

Чтобы избежать проблем с кодировкой, просто добавьте параметры encoding="cp437" и errors='ignore' в ваш код как при чтении, так и при записи файла. Вот пример:

open('filename.csv', encoding="cp437", errors='ignore')
open(file_name, 'w', newline='', encoding="cp437", errors='ignore')

Удачи!

0

Код ниже кодирует символы UTF-8:

with open("./website.html", encoding="utf8") as file:
    contents = file.read()

Этот фрагмент открывает файл website.html в кодировке UTF-8 и считывает его содержимое. Указание параметра encoding="utf8" гарантирует, что текст будет правильно обработан, даже если в нем содержатся символы, выходящие за пределы стандартного ASCII.

0

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

open(filename, 'rb')

где r = чтение, b = двухбайтовый режим.

0

TLDR: Попробуйте: file = open(filename, encoding='cp437')

Почему? Когда мы используем:

file = open(filename)
text = file.read()

Python предполагает, что файл использует ту же кодировку, что и текущая среда (например, cp1252 в случае вопроса), и пытается декодировать его в свой стандартный UTF-8. Если файл содержит символы с кодами, не определёнными в этой кодировке (например, 0x90), мы получаем UnicodeDecodeError. Иногда мы не знаем кодировку файла, иногда она может не обрабатываться в Python (например, cp790), а иногда файл может содержать смешанные кодировки.

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

file = open(filename, errors='replace')

Другой вариант — использовать:

file = open(filename, errors='ignore')

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

Очень хорошее решение — указать кодировку, причем не любую (как cp1252), а такую, которая отображает каждое однобайтовое значение (0..255) на символ (например, cp437 или latin1):

file = open(filename, encoding='cp437')

Кодовая страница 437 — это просто пример. Это оригинальная DOS-кодировка. Все коды сопоставлены, поэтому при чтении файла нет ошибок, ошибки не маскируются, символы сохраняются (хотя и не остаются полностью нетронутыми, но всё равно остаются различимыми), и вы можете проверить их значения с помощью ord().

Обратите внимание, что этот совет является лишь быстрым обходным решением для неприятной проблемы. Правильное решение — использовать бинарный режим, хотя это и не так быстро.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь