Python считает, что текстовый файл длиной 3000 строк занимает одну строку? - PullRequest
11 голосов
/ 02 февраля 2010

У меня очень длинный текстовый файл, который я пытаюсь обработать с помощью Python.

Однако следующий код:

for line in open('textbase.txt', 'r'):
    print 'hello world'

производит только следующий вывод:

hello world

Похоже, что Python считает, что файл имеет длину только одну строку, хотя при просмотре в текстовом редакторе он составляет много тысяч строк. Изучение его в командной строке с помощью команды file дает:

$ file textbase.txt
textbase.txt: Big-endian UTF-16 Unicode English text, with CR line terminators

Что-то не так? Нужно ли менять терминаторы строки?

Ответы [ 4 ]

25 голосов
/ 02 февраля 2010

Согласно документации для open(), вы должны добавить U в режим:

open('textbase.txt', 'Ur')

Это разрешает " универсальные переводы строк ", что нормализует их до \n в строках, которые оно вам дает.

Тем не менее, правильное решение - декодировать UTF-16BE в объекты Unicode сначала , прежде чем переводить переводы строки. В противном случае, случайный 0x0d байт может быть ошибочно превращен в 0x0a, в результате чего

UnicodeDecodeError: кодек «utf16» не может декодировать байт 0x0a в позиции 12: усеченные данные.

Модуль Python codecs предоставляет функцию open, которая может декодировать Unicode и обрабатывать символы новой строки одновременно:

import codecs
for line in codecs.open('textbase.txt', 'Ur', 'utf-16be'):
    ...

Если файл имеет метку порядка байтов (BOM), и вы указываете 'utf-16', тогда он обнаруживает порядковый номер и скрывает BOM для вас. Если этого не произойдет (поскольку спецификация является необязательной), то этот декодер просто продолжит работу и будет использовать порядковый номер вашей системы, что, вероятно, не будет хорошо.

Указание порядка байтов самостоятельно (с помощью 'utf-16be') не скроет спецификацию, поэтому вы можете использовать этот хак:

import codecs
firstline = True
for line in codecs.open('textbase.txt', 'Ur', 'utf-16be'):
    if firstline:
        firstline = False
        line = line.lstrip(u'\ufeff')

См. Также: Python Unicode HOWTO

6 голосов
/ 02 февраля 2010

Вы, вероятно, обнаружите, что именно "с терминаторами линии CR" выдает игру. Если вы работаете на платформе, которая использует переводы строк в качестве разделителей строк, будет видеть ваш файл в виде одной большой строки honkin '.

Измените ваш входной файл, чтобы он использовал правильные разделители строк. Ваш редактор, вероятно, более щадящий, чем ваша реализация Python.

Насколько мне известно, окончания строк CR - это Mac, и вы можете использовать модификатор режима U для open для автоматического определения на основе найденного ограничителя первой строки.

1 голос
/ 02 февраля 2010

похоже, ваш файл имеет строки, оканчивающиеся только CR, а Python, вероятно, ожидает LF или CRLF. Попробуйте использовать «универсальный перевод строки»:

for line in open('textbase.txt', 'rU'):
    print 'hello world'

http://docs.python.org/library/functions.html?highlight=open#open

0 голосов
/ 02 февраля 2010

open() возвращает файловый объект. Вам необходимо использовать:

for line in open('textbase.txt', 'r').readlines():
    print line
...