Python为何将一个3000行的文本文件识别为一行?
我有一个非常长的文本文件,想用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 个回答
看起来你的文件中的行是用CR来结束的,而Python可能期待的是LF或者CRLF。你可以试试使用“通用换行符”:
for line in open('textbase.txt', 'rU'):
print 'hello world'
http://docs.python.org/library/functions.html?highlight=open#open
你可能会发现,“带有CR行结束符”的设置是问题的关键。如果你在一个使用换行符作为行结束符的平台上工作,它会把你的文件当作一整行来处理。
你需要修改你的输入文件,确保它使用正确的行结束符。你的编辑器可能对这个问题比较宽容,而你的Python程序可能就不那么友好了。
CR行结束符是Mac系统特有的,至于我所知道的,你可以在使用open
时加上U
模式,这样它会根据找到的第一个行结束符自动识别。
根据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')