UnicodeDecodeError: Кодек 'charmap' не может декодировать байт X в позиции Y: символ отображается как <неопределённый>
Я пытаюсь сделать некоторые манипуляции с текстовым файлом, заполненным информацией, используя программу на 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 ответ(ов)
Файл, о котором идет речь, не использует кодировку CP1252. Он использует другую кодировку, которую вам придется определить самостоятельно. Наиболее распространенные кодировки — это Latin-1 и UTF-8. Поскольку 0x90 на самом деле ничего не значит в Latin-1, вероятнее всего, это UTF-8 (где 0x90 является байтом продолжения).
Вы можете указать кодировку при открытии файла:
file = open(filename, encoding="utf8")
Чтобы избежать проблем с кодировкой, просто добавьте параметры encoding="cp437"
и errors='ignore'
в ваш код как при чтении, так и при записи файла. Вот пример:
open('filename.csv', encoding="cp437", errors='ignore')
open(file_name, 'w', newline='', encoding="cp437", errors='ignore')
Удачи!
Код ниже кодирует символы UTF-8:
with open("./website.html", encoding="utf8") as file:
contents = file.read()
Этот фрагмент открывает файл website.html
в кодировке UTF-8 и считывает его содержимое. Указание параметра encoding="utf8"
гарантирует, что текст будет правильно обработан, даже если в нем содержатся символы, выходящие за пределы стандартного ASCII.
Если вам не нужно декодировать файл, например, при загрузке файла на сайт, используйте:
open(filename, 'rb')
где r = чтение, b = двухбайтовый режим.
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()
.
Обратите внимание, что этот совет является лишь быстрым обходным решением для неприятной проблемы. Правильное решение — использовать бинарный режим, хотя это и не так быстро.
Фиксация количества знаков после запятой с помощью f-строк
Что такое __pycache__?
Найти все файлы с расширением .txt в директории на Python
Как открыть несколько файлов с помощью "with open" в Python?
Вывод строки в текстовый файл