Python 2.7: len() 对包含换行符的文件行返回错误值

3 投票
3 回答
2380 浏览
提问于 2025-04-18 18:44

我在64位的Windows 7上使用WinPython 2.7。

我想打开一个文件,逐行读取内容,当遇到某个特定的序列时,我想从那里继续处理文件内容。

为了保存当前的位置,我把当前行的长度添加到一个行长度的列表里。但是,len(line)返回的值比实际少了1。我怀疑这可能和Windows的换行符\r\n有关。

下面是一个示例代码。

  • testfile.txt:

     Line1
     Line2
     Line3
    
  • test.py

     fn = 'testfile.txt'
    
     f = open(fn)
    
     line_offsets = []
     for line in f:
         line_offsets.append(len(line))
    
     f.seek(line_offsets[1])
     print '%r' % f.read()
    
  • 输出结果:

     '\nLine2\nLine3'
    
  • 预期输出:

     'Line2\nLine3'
    

我尝试通过指定读取方法来打开文件(使用通用换行符):f = open(fn, 'rU'),但这也没有解决问题。如果我以二进制模式打开文件是可以的,但这个实际上是一个文本文件,而不是二进制文件,所以我想避免这样做,同时我也想搞清楚这里发生了什么。

3 个回答

0

为了实现你想要的效果,你可以在读取每一行之前,先调用一下 f.tell(),然后再用 f.readline() 来读取这一行。由于某些原因,你可能还需要以二进制模式打开文件,这和 Windows系统中tell()的一个问题有关,同时你也需要自己处理行结束符的问题。直接把文件当成一个迭代器来用是行不通的,因为这样会有缓存,可能会导致文件指针移动到你正在读取的行的后面。

>>> with open('testfile.txt', 'rb') as f:
...     while True:
...         here = f.tell()
...         line = f.readline()
...         if not line:
...             break
...         print('%02d\t%r' % (here, line))
... 
00  'Line1\n'
06  'Line2\n'
12  'Line3\n'
0

你可以使用 splitlines() 这个方法来获取文件中的每一行。这个方法能够处理不同类型的换行符,具体的可以参考 文档

4

以二进制模式打开文件,这样行中的 '\r' 就不会被去掉了。这样 len 就能正确返回字节数。

f = open(fn, 'rb')

如果你要迁移到 Python 3,这一点特别重要,因为非二进制文件在读取时会把字节解码成 Unicode 字符,这样计算的数量可能会大大不准确。

撰写回答