Ответ 1
Ваш файл, по-видимому, не использует кодировку UTF-8. При открытии файла важно использовать правильный кодек.
open()
вы можете рассказать, как обрабатывать ошибки декодирования, с помощью ключевого слова errors
:
error является необязательной строкой, которая определяет, как должны обрабатываться ошибки кодирования и декодирования - это нельзя использовать в двоичном режиме. Доступно множество стандартных обработчиков ошибок, хотя любое имя обработки ошибок, зарегистрированное с помощью
codecs.register_error()
, также допустимо. Стандартные имена:
'strict'
, чтобы вызвать исключениеValueError
, если есть ошибка кодирования. Значение по умолчаниюNone
имеет тот же эффект.'ignore'
игнорирует ошибки. Обратите внимание, что игнорирование ошибок кодирования может привести к потере данных.'replace'
вызывает вставку замещающего маркера (например, "?") В случае искаженных данных.'surrogateescape'
будет представлять любые неправильные байты как кодовые точки в Частной области использования Юникода в диапазоне от U + DC80 до U + DCFF. Эти частные кодовые точки будут затем возвращаться в те же байты, когда при записи данных используется обработчик ошибокsurrogateescape
. Это полезно для обработки файлов в неизвестной кодировке.'xmlcharrefreplace'
поддерживается только при записи в файл. Символы, не поддерживаемые кодировкой, заменяются соответствующей ссылкой на символ XML&#nnn;
.'backslashreplace'
(также поддерживается только при записи) заменяет неподдерживаемые символы на escape-последовательности с обратной косой чертой Pythons.
Открытие файла с помощью чего-либо, кроме 'strict'
('ignore'
, 'replace'
и т.д.), Позволит вам прочитать файл без возражений.
Обратите внимание, что декодирование происходит для каждого буферизованного блока данных, а не для текстовой строки. Если вам необходимо построчно обнаруживать ошибки, используйте обработчик surrogateescape
и проверяйте каждую прочитанную строку на наличие кодовых точек в суррогатном диапазоне:
import re
_surrogates = re.compile(r"[\uDC80-\uDCFF]")
def detect_decoding_errors_line(l, _s=_surrogates.finditer):
"""Return decoding errors in a line of text
Works with text lines decoded with the surrogateescape
error handler.
Returns a list of (pos, byte) tuples
"""
# DC80 - DCFF encode bad bytes 80-FF
return [(m.start(), bytes([ord(m.group()) - 0xDC00]))
for m in _s(l)]
Э.Г.
with open("test.csv", encoding="utf8", errors="surrogateescape") as f:
for i, line in enumerate(f, 1):
errors = detect_decoding_errors_line(line)
if errors:
print(f"Found errors on line {i}:")
for (col, b) in errors:
print(f" {col + 1:2d}: {b[0]:02x}")
Примите во внимание, что не все ошибки декодирования могут быть исправлены изящно. Хотя UTF-8 спроектирован так, чтобы быть устойчивым к небольшим ошибкам, другие многобайтовые кодировки, такие как UTF-16 и UTF-32, не могут справиться с отброшенными или лишними байтами, что затем повлияет на точность разделителей строк. расположены. Приведенный выше подход может привести к тому, что остальная часть файла будет обрабатываться как одна длинная строка. Если файл достаточно велик, это может, в свою очередь, привести к исключению MemoryError
, если "строка" достаточно велика.