Python: отменить операцию чтения файла (), чтобы указатель файла вернулся в исходное состояние - PullRequest
32 голосов
/ 17 августа 2010

Я просматриваю указатель файла Python на текстовый файл в режиме только для чтения, используя file.readline (), ища специальную строку.Как только я нахожу эту строку, я хочу передать указатель файла методу, который ожидает, что указатель файла будет в состоянии START этой строки чтения (не сразу после нее).

Как мне, по сути, отменить один файл.Операция readline () над указателем файла?

Ответы [ 5 ]

43 голосов
/ 17 августа 2010

Вы должны запомнить положение, вызвав file.tell() перед readline, а затем позвонив 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()

Я не могу вспомнить, безопасно ли вызывать file.seek() внутри цикла for line in file, поэтому я обычно просто записываю цикл while.Вероятно, есть гораздо более питонный способ сделать это.

11 голосов
/ 17 августа 2010

Вы записываете начальную точку линии с помощью thefile.tell() перед вызовом readline и возвращаетесь к этой точке, если вам нужно, с 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'
>>> 

, как выВидите, поиск / передача "pair" является "отменой", так сказать, перемещения указателя файла, выполняемого readline.Конечно, это может работать только с фактическим файлом, который можно искать (т. Е. С диском), а не (например, с файловыми объектами, созданными с помощью метода make-файлов с сокетами и т. Д. И т. Д.)

4 голосов
/ 17 августа 2010

Если ваш метод просто хочет выполнить итерацию по файлу, тогда вы можете использовать itertools.chain для создания подходящего итератора:

import itertools

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
1 голос
/ 17 августа 2010
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
0 голосов
/ 28 августа 2018

Если вы не знаете последнюю строку, потому что не посещали ее, вы можете читать назад, пока не увидите символ новой строки:

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
...