文件处理中的seek()问题

0 投票
3 回答
3914 浏览
提问于 2025-04-16 14:14

我在处理一个文件,这个文件里面有很多文件名,还有一些关于这个文件处理过程的日志,其中有些日志记录了错误。我是逐行读取的,如果遇到错误,我想把两个文件名之间的所有内容都记录下来。

当我使用seek这个功能时,我觉得它不是把指针移动到我想要的那一行,而是移动到了字符#的位置。例如:

f=open("fileblah",'r')
while f:
   line=f.readline()
   counter=counter+1
   f.seek(tail_position) # i want the next loop to start from after the error happened.

   if line.startswith("D:")
      header_position=counter
      error_flag=0 #unset error flag
   if line.startswith("error")
        error_flag=1       #set error_flag           
        while(not(line.startswith("D:"): #go until next file beginning
           line=f.readline()
           counter=counter+1
        tail_position=counter #have come to the next filename

我知道这样做效率很低,但实际上它根本不管用,因为f.seek(tail_position)把文件指针移动到了字符#的位置,而不是我想要的那一行。

3 个回答

0

就像标准输入输出库里的 fseek() 函数,seek(offset[,whence]) 也是用来设置当前的位置。whence 默认值是 0。所以你可以这样做:

while(not(line.startwith("D:"))):
      fseek(tail_position,'\n')
      tail_position ++
1

seek() 这个函数通常用于随机访问文件的读取。如果你要读取的文件本身就是文本格式,并且可以逐行读取,那么你只需要读取一行,然后对这一行进行字符串操作就可以了。这样就不需要移动文件的读取位置。

你的代码只需要像这样写:

for line in f:  
    do_stuff_with line
3

使用 .tell() 来记录你当前行的起始位置,然后你可以用 .seek() 回到这个位置。

编辑:我觉得这就是你想要的:

def errorsInLog(fname, newfileStr='D:', iserrorStr='error'):
    with open(fname) as inf:
        prev = pos = inf.tell()
        line = inf.readline()
        error = False

        while line:
            if line.startswith(newfileStr):
                if error:
                    inf.seek(prev)
                    yield(inf.read(pos-prev))
                prev = pos
                error = False
            elif line.startswith(iserrorStr):
                error = True

            pos = inf.tell()
            line = inf.readline()

        if error:
            inf.seek(prev)
            yield(inf.read())

def main():
    print('\n\n'.join(errorsInLog('fileblah')))

对于每个文件名后面跟着的错误,它会返回一个字符串,这个字符串包含了文件名和所有后面的行,直到下一个文件名或者文件结束为止。

撰写回答