Правильный способ загрузки текста Unicode из Python 2.7 выглядит примерно так:
content = open('filename').read().decode('encoding'):
for line in content.splitlines():
process(line)
(Обновление:Нет, это не так. Смотрите ответы.)
Однако, если файл очень большой, я мог бы захотеть читать, декодировать и обрабатывать его по одной строке за раз, чтобы весь файл никогда не загружался в память сразу. Что-то вроде:
for line in open('filename'):
process(line.decode('encoding'))
Итерация цикла for
по открытому дескриптору файла представляет собой генератор, считывающий по одной строке за раз.
Однако это не работает, потому что, например, если файл закодирован в utf32, то байты в файле (в шестнадцатеричном формате )выглядят примерно так:
hello\n = 68000000(h) 65000000(e) 6c000000(l) 6c000000(l) 6f000000(o) 0a000000(\n)
И разделение на строки, выполненное циклом for
, разбивается на байт 0a
символа \n
, в результате чего (в шестнадцатеричном формате):
lines[0] = 0x 68000000 65000000 6c000000 6c000000 6f000000 0a
lines[1] = 0x 000000
Таким образом, часть символа \n
остается в конце строки 1, а оставшиеся три байта заканчиваются в строке 2 (, за которой следует любой текст, фактически находящийся в строке 2. )Вызов decode
на любой из эти строки по понятным причинам приводят к UnicodeDecodeError
.
UnicodeDecodeError: 'utf32' codec can't decode byte 0x0a in position 24: truncated data
Таким образом, очевидно, что разделение потока байтов Unicode на 0a
байтов не является правильным способом разделения его на строки. Вместо этого я должен разбивать на вхождения полных четырех -байтовых символов новой строки (0x0a000000 ). Однако я думаю, что правильный способ обнаружения этих символов - это декодировать поток байтов в строку юникода и искать символы \n
-, и это декодирование полного потока - это именно та операция, которую я пытаюсь избежать.
Это не может быть необычным требованием. Как правильно с этим справиться?