使用迭代器从file.tell()获得重要的偏移量

时间:2017-10-12 18:35:41

标签: python python-2.7 file-io

查看 file.tell(),我希望它能给我一个可以用于 file.seek()的职位。但我不确定如何在实践中这样做,因为tell()似乎从一开始就指向文件的末尾。

这里有一些测试数据:

i am line 1
i am line 2
i am line 3

程序:

with open("./test_tell.txt") as fi:
    for line in fi:
        seekto = fi.tell()
        print "position:%d" % fi.tell()
        print(line)

    #we're at the end
    fi.seek(seekto)
    print("seekto:%s" % fi.read())

    fi.seek(seekto-5)
    print("seekto-5:%s" % fi.read())
输出:
position:35
i am line 1

position:35
i am line 2

position:35
i am line 3
seekto:
seekto-5:ine 3

请注意我从一开始就到达35,文件结尾?我怎样才能使迭代器只在前进到每一行的末尾,这样tell实际上对知道我在文件中的位置很有用?我感觉整个文件被读作优化,这就是为什么告诉我最后的权利。

我关心的原因是我正在研究一个基于状态机的程序,该程序运行在一个大文件中。出于调试目的,我想提供一个 n行返回窗口,当前行和前面的n行。希望寻求使用tell位置来提前读取同一文件的不同文件。因为告诉我总是指出结束。

Python 2.7,以防文件语义发生变化。

1 个答案:

答案 0 :(得分:2)

您的示例不会在Python 2中触发错误,但是因为性能原因,因为使用迭代器读取缓冲会失败。

大多数情况下,当您逐行阅读时,您并不关心文件位置(更一般地说:您不关心文本文件中的文件位置)

因此在1次操作中读取文件,留下文件的结束偏移量。

请注意,Python 3更严格:在迭代后使用tell获得异常。

OSError: telling position disabled by next() call

一种方法是

  • 二进制模式打开文件(Windows,否则,由于回车字符,您将有班次)
  • 阅读&通过添加当前行的长度来计算位置

我的代码:适用于python 2& python 3(需要解码才能摆脱字节表示以更好地完成):

with open("./text.txt","rb") as fi:
    current_offset = 0
    line_pos=[]
    for line in fi:
        line_pos.append(current_offset)
        current_offset += len(line)
        print(line)

    fi.seek(line_pos[1])
    print("seekto:%s" % next(fi))

结果:

b'i am line 1\r\n'
b'i am line 2\r\n'
b'i am line 3\r\n'
seekto:b'i am line 2\r\n'

请注意,我在第二行的开头成功搜索,因此next(fi)读取了第二行。

当然,它仍然可以将行存储在list中,除非它太大,在这种情况下这种方法有一些兴趣(即:如果文件是没有被其他进程写回,否则线路偏移信息需要更新)