Python为何将一个3000行的文本文件识别为一行?

11 投票
4 回答
2156 浏览
提问于 2025-04-15 18:47

我有一个非常长的文本文件,想用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 个回答

1

看起来你的文件中的行是用CR来结束的,而Python可能期待的是LF或者CRLF。你可以试试使用“通用换行符”:

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

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

6

你可能会发现,“带有CR行结束符”的设置是问题的关键。如果你在一个使用换行符作为行结束符的平台上工作,它会把你的文件当作一整行来处理。

你需要修改你的输入文件,确保它使用正确的行结束符。你的编辑器可能对这个问题比较宽容,而你的Python程序可能就不那么友好了。

CR行结束符是Mac系统特有的,至于我所知道的,你可以在使用open时加上U模式,这样它会根据找到的第一个行结束符自动识别。

25

根据open()的文档,你应该在模式中加一个U

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

这样可以启用“通用换行符”,它会把换行符统一成\n,这样你得到的字符串就会一致。

不过,正确的做法是先把UTF-16BE解码成Unicode对象,然后再处理换行符。否则,有可能会把0x0d这个字节错误地转成0x0a,这样就会出现

UnicodeDecodeError: 'utf16' codec can't decode byte 0x0a in position 12: truncated data.

Python的codecs模块提供了一个open函数,可以同时解码Unicode和处理换行符:

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

如果文件有字节顺序标记(BOM),而你指定'utf-16',那么它会自动检测字节顺序并为你隐藏BOM。如果没有BOM(因为BOM是可选的),那么这个解码器会使用你系统的字节顺序,这可能就不太好了。

如果你自己指定字节顺序(用'utf-16be'),那么BOM就不会被隐藏,所以你可能需要使用这个小技巧:

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 使用指南

撰写回答