次のような巨大なファイルがあります。
7
bla1
blala
blabla
blab
blals
blable
bla
more here..
最初の数字は、私が持つ値の数を示しています。問題は、11 行目 (テキスト「more here..」) を直接ポイントしたいだけで、以前にこれらの値をすべて読み取る必要がないということです。私の場合、大量の数値があるため、最適化する必要があります。
何かお勧めしますか?
File#seekを使用して、ファイルにランダムにアクセスできます。
このアプローチの問題は、行オフセットではなく、指定されたバイト オフセットでデータにアクセスするだけになることです。ファイルの先頭からリストが終了するまでのバイトオフセットをファイルで指定できる場合は、それを使用できます。
最初の N 行をスキップするファイルのようなものを作成できます。
SkipFile.open("/tmp/frarees") do |ln|
puts ln # "more here.." and so on
end
puts SkipFile.new("/tmp/frarees").readline # "more here.."
そのようです:
class SkipFile
def self.open(fn, &block)
sf = SkipFile.new(fn)
return sf unless block
sf.each(&block)
end
def initialize(fn)
@f = File.open(fn)
skip = @f.readline.to_i # Skip N lines as prescribed by the file
skip.times { @f.readline } # this could be done lazily
end
def each(&block)
@f.each(&block)
end
def readline
@f.readline
end
end
ファイルの行を順方向に反復したいだけであれば、簡単に実行できます。File
ただし、またはIO
インターフェースを正確に模倣したい場合 (ただし、を参照Delegate
)、特にファイルの偽の開始点まで巻き戻す機能をサポートしたい場合は、困難になります。
ファイル全体を一度にメモリにロードする必要があるため、おそらくあまり効率的ではありませんが、これを行うエレガントな方法を次に示します。
File.readlines(file_path)[10..-1] # indexing starts from 0
ファイル内のバイトを読み取って「行」とは何かを判断するため、これよりも効率的になるとは思いません。
f = File.open('./data')
(f.readline.to_i + 2).times { f.readline }
p f.readline