【问题标题】:Undo a file readline() operation so file-pointer is back in original state撤消文件 readline() 操作,使文件指针回到原始状态
【发布时间】:2011-03-31 03:32:31
【问题描述】:

我正在使用 file.readline() 以只读模式浏览文本文件的 Python 文件指针,以查找特殊行。一旦我找到该行,我想将文件指针传递给一个方法,该方法期望文件指针位于该 readline 的 START(而不是紧随其后)。

我如何从根本上撤消对文件指针的一个 file.readline() 操作?

【问题讨论】:

    标签: python file-io readline readlines


    【解决方案1】:

    如果您的方法只是想遍历文件,那么您可以使用itertools.chain 来制作适当的迭代器:

    import itertools
    
    # do something to the marker line and everything after
    def process(it):
        for line in it:
            print line,
            
    with open(filename,'r') as f:
        for line in f:
            if 'marker' in line:
                it=itertools.chain((line,),f)
                process(it)
                break
    

    【讨论】:

      【解决方案2】:

      如果您不知道最后一行,因为您没有访问它,您可以向后阅读,直到看到换行符:

      with open(logfile, 'r') as f:
          # go to EOF
          f.seek(0, os.SEEK_END)
          nlines = f.tell()
          i=0
          while True:
              f.seek(nlines-i)
              char = f.read(1)
              if char=='\n':
                  break
              i+=1
      

      【讨论】:

        【解决方案3】:
        fin = open('myfile')
        for l in fin:
            if l == 'myspecialline':
                # Move the pointer back to the beginning of this line
                fin.seek(fin.tell() - len(l))
                break
        # now fin points to the start of your special line
        

        【讨论】:

        • 我的想法和你一样,但 file.seek 帮助建议不然:If the file is opened in text mode, only offsets returned by tell() are legal.
        • 这个我用过几次都没有问题,估计是和其他字符编码有关
        • 在文本模式下,\r\n 将转换为\n,因此您将丢失一个字符。在这种情况下,该字符将是 CR (\r),所以没有人注意到 ;)
        【解决方案4】:

        在调用readline 之前用thefile.tell() 记录行的起点,如果需要,用thefile.seek 回到该点。

        >>> with open('bah.txt', 'w') as f:
        ...   f.writelines('Hello %s\n' % i for i in range(5))
        ... 
        >>> with open('bah.txt') as f:
        ...   f.readline()
        ...   x = f.tell()
        ...   f.readline()
        ...   f.seek(x)
        ...   f.readline()
        ... 
        'Hello 0\n'
        'Hello 1\n'
        'Hello 1\n'
        >>> 
        

        如您所见,seek/tell “pair”正在“撤消”,可以说是readline 执行的文件指针移动。当然,这只适用于实际的可查找(即磁盘)文件,而不适用于(例如)使用套接字的 makefile 方法构建的类似文件的对象等。

        【讨论】:

          【解决方案5】:

          您必须通过在 readline 之前调用 file.tell() 来记住位置,然后调用 file.seek() 来回退。比如:

          fp = open('myfile')
          last_pos = fp.tell()
          line = fp.readline()
          while line != '':
            if line == 'SPECIAL':
              fp.seek(last_pos)
              other_function(fp)
              break
            last_pos = fp.tell()
            line = fp.readline()
          

          我不记得在for line in file 循环内调用file.seek() 是否安全,所以我通常只写出while 循环。可能有一种更 Pythonic 的方式来做到这一点。

          【讨论】:

          • 在文件循环中调用 for 行似乎并不安全。 "OSError: 告诉位置被 next() 调用禁用"
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-11-23
          • 2022-12-17
          • 2011-09-07
          相关资源
          最近更新 更多