ファイルを開いて、ファイルのどこかでseek()を実行するとします。現在のファイル行をどのようにして知ることができますか?
(私はファイルをスキャンした後にシーク位置を行にマップするアドホックファイルクラスで個人的に解決しましたが、他のヒントを見て、この質問をスタックオーバーフローに追加したかったので、どこでも問題を見つけることができませんでしたグーグル)
ファイルを開いて、ファイルのどこかでseek()を実行するとします。現在のファイル行をどのようにして知ることができますか?
(私はファイルをスキャンした後にシーク位置を行にマップするアドホックファイルクラスで個人的に解決しましたが、他のヒントを見て、この質問をスタックオーバーフローに追加したかったので、どこでも問題を見つけることができませんでしたグーグル)
seek() を使用すると、Python はポインタ オフセットを使用してファイル内の目的の位置にジャンプします。ただし、現在の行番号を知るには、その位置までの各文字を調べる必要があります。したがって、read() を優先して seek() を放棄することもできます。
交換
f = open(filename, "r")
f.seek(55)
と
f = open(filename, "r")
line=f.read(55).count('\n')+1
print(line)
f.read(num) は、num が非常に大きい場合に大量のメモリが必要になる可能性があるため、おそらく使用したくないでしょう。その場合、次のようなジェネレーターを使用できます。
import itertools
import operator
line_number=reduce(operator.add,( f.read(1)=='\n' for _ in itertools.repeat(None,num)))
pos=f.tell()
f.seek(num)
これは、 を与える追加の利点と同等ですline_number
。
できるだけ多くの怠惰を使用して、問題にアプローチする方法は次のとおりです。
from random import randint
from itertools import takewhile, islice
file = "/etc/passwd"
f = open(file, "r")
f.seek(randint(10,250))
pos = f.tell()
print "pos=%d" % pos
def countbytes(iterable):
bytes = 0
for item in iterable:
bytes += len(item)
yield bytes
print 1+len(list(takewhile(lambda x: x <= pos, countbytes(open(file, "r")))))
少し読みにくいが、より怠惰なアプローチの場合は、 and を使用enumerate
しdropwhile
ます。
from random import randint
from itertools import islice, dropwhile
file = "/etc/passwd"
f = open(file, "r")
f.seek(randint(10,250))
pos = f.tell()
print "pos=%d" % pos
def countbytes(iterable):
bytes = 0
for item in iterable:
bytes += len(item)
yield bytes
print list(
islice(
dropwhile(lambda x: x[1] <= pos, enumerate(countbytes(open(file, "r"))))
, 1))[0][0]+1