Мне нужно обработать огромный текстовый файл, и мой код выглядит следующим образом:
freq_counter = collections.Counter()
unigram_counter = collections.Counter()
with open(filename, 'r', encoding='utf8') as f:
for i, batch in enumerate(read_batch(f, batch_size=1000)):
logger.info("Batch {}".format(str(i)))
frequency_with_batch(batch, freq_counter, unigram_counter, enable)
if data_batch == i+1:
break
def read_batch(file_handle, batch_size=1000):
batch = []
for line in file_handle:
if not line:
continue
batch.append(line)
if len(batch) == batch_size:
yield batch
batch.clear()
if batch:
yield batch
Encoding='utf8' работало хорошо, пока не обработала середину большого текстового файла. В определенной строке он сообщил о следующей ошибке:
File "/data5/congmin/tool/utils/my_utils.py", line 484, in read_batch
for line in file_handle:
File "/usr/lib/python3.6/codecs.py", line 321, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode bytes in position 6084-6085: invalid continuation byte
Означает ли это, что какой-то текст в одном и том же файле закодирован в utf8, а какой-то не в utf8? Я провел поиск в Интернете, и некоторые предложили использовать encoding='latin-1' или encoding="ISO-8859-1". Обычно я использую utf8 для чтения и записи в файл. Для такого большого файла или большого количества текстовых файлов, как мне использовать параметр кодирования, если utf8 работает большую часть времени?
РЕДАКТИРОВАТЬ: Я изменил кодировку = utf8 на ISO-8859-1, сообщение об ошибке исчезло. Однако символы, выводимые в текстовый файл, не читаются, как показано ниже:
ï¼ 2225
ä¸ 1412
533
å 467
å¤ 418
å 417
ДОБАВЛЕНИЕ:
Я установил команду 'file' на свой Ubuntu и обнаружил кодировку файла:
file all.txt
all.txt: UTF-8 Unicode text, with very long lines
так что на самом деле это файл utf-8. Если это utf8, почему возникает ошибка?
Файлы могут быть закодированы с использованием различных кодировщиков. Ненормально смешивать кодировки в одном файле, но если файл на самом деле не был закодирован в UTF-8, он не будет работать с первым байтом, который нарушает правила кодирования UTF-8. Кодер вроде Latin-1 никогда не подведет, но если файл не закодирован в Latin-1, он будет неправильно декодировать неправильные символы.
@MarkTolonen Какое решение этой проблемы? Для такого огромного файла это может происходить часто?
Решение состоит в том, чтобы использовать правильную кодировку для файла. Если вы этого не знаете, есть инструменты для угадывания, но они не всегда угадывают правильно
Если файл не utf-8, почему он правильно обработал большую часть файла? Я подозреваю, что это может быть связано с некоторыми специальными символами. Весь файл может быть еще utf8? Какая связь между кодировкой файла и кодировкой символов?
UTF8 следует определенным правилам кодирования. Декодирование файла работает до тех пор, пока в последовательности не будет прочитан байт, нарушающий правила.
Вы должны внимательно проверить байты, в которых у вас есть ошибки (и, возможно, записать их туда). Как уже было сказано, некоторые файлы могут иметь несколько кодировок (это было часто в старых файлах). Но это может быть просто артефакт программы (или почтового клиента), который может разбивать строки/символы в середине последовательности. Хороший способ отладки: в
open
добавьте, error="backslashreplace")
, а затем посмотрите на текст, где у вас есть\x..