Как решить эту проблему с юникодом при чтении текстового файла?

avatar
marlon
9 августа 2021 в 03:41
564
1
0

Мне нужно обработать огромный текстовый файл, и мой код выглядит следующим образом:

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, почему возникает ошибка?

Источник
Mark Tolonen
9 августа 2021 в 03:50
1

Файлы могут быть закодированы с использованием различных кодировщиков. Ненормально смешивать кодировки в одном файле, но если файл на самом деле не был закодирован в UTF-8, он не будет работать с первым байтом, который нарушает правила кодирования UTF-8. Кодер вроде Latin-1 никогда не подведет, но если файл не закодирован в Latin-1, он будет неправильно декодировать неправильные символы.

marlon
9 августа 2021 в 03:54
0

@MarkTolonen Какое решение этой проблемы? Для такого огромного файла это может происходить часто?

Mark Tolonen
9 августа 2021 в 03:55
0

Решение состоит в том, чтобы использовать правильную кодировку для файла. Если вы этого не знаете, есть инструменты для угадывания, но они не всегда угадывают правильно

marlon
9 августа 2021 в 03:58
0

Если файл не utf-8, почему он правильно обработал большую часть файла? Я подозреваю, что это может быть связано с некоторыми специальными символами. Весь файл может быть еще utf8? Какая связь между кодировкой файла и кодировкой символов?

Mark Tolonen
9 августа 2021 в 04:41
0

UTF8 следует определенным правилам кодирования. Декодирование файла работает до тех пор, пока в последовательности не будет прочитан байт, нарушающий правила.

Giacomo Catenazzi
9 августа 2021 в 07:23
0

Вы должны внимательно проверить байты, в которых у вас есть ошибки (и, возможно, записать их туда). Как уже было сказано, некоторые файлы могут иметь несколько кодировок (это было часто в старых файлах). Но это может быть просто артефакт программы (или почтового клиента), который может разбивать строки/символы в середине последовательности. Хороший способ отладки: в open добавьте , error="backslashreplace"), а затем посмотрите на текст, где у вас есть \x..

Ответы (1)

avatar
BoarGules
9 августа 2021 в 04:55
0

Похоже, ваш файл имеет кодировку UTF-8, но в нем есть недопустимые байты. Чтобы подавить исключение и понять, что не так, откройте файл с помощью errors='backslashreplace'. Это позволит вам прочитать весь файл и просмотреть проблемный фрагмент. Из ваших предыдущих сообщений вы уже знаете расположение первого недопустимого байта. Это может быть что-то такое же простое, как цитата из другого документа. в другой кодировке. (Не должно происходить, но происходит.) Или это может быть поврежденный файл. (То же самое.)

marlon
9 августа 2021 в 16:16
0

'backslashreplace' - это ключевое слово, используемое в Python?

BoarGules
9 августа 2021 в 18:07
0

Нет. Обратите внимание, что это в кавычках. Параметр от errors до open() принимает несколько задокументированных значений string.