2012-01-18 13 views
1

かなり大きいファイルを特定の文字列で検索し、そのオフセットを返そうとしています。私は、LUAに新たなんだと、私の現在のアプローチは、次のようになります。luaで文字列を返す

linenumber = 0 
for line in io.lines(filepath) do 
result=string.find(line,"ABC",1) 
linenumber = linenumber+1 

if result ~= nil then 
offset=linenumber*4096+result 
io.close 
end 
end 

私はこの方法はかなり原始的で確かに遅いことを実現します。どうすればこれをより効率的に行うことができますか?

ありがとうございます。

答えて

2

ファイルが大きすぎず、メモリを節約してください。ファイル全体をスラップするだけで、速くてstring.findを使用してください。そうでなければ、ブロック単位でファイルを検索できます。

あなたのアプローチはそれほど悪くはありません。私は重複するブロックでファイルをロードすることをお勧めします。

".... ...A BC.. ...." 

私の実装では、このように書き:あなたのファイルが実際にラインを持っている場合

size=4096 -- note, size should be bigger than the length of pat to work. 
pat="ABC" 
overlap=#pat 
fh=io.open(filepath,'rb') -- On windows, do NOT forget the b 
block=fh:read(size+overlap) 
n=0 
while block do 
    block_offset=block:find(pat) 
    if block_offset then 
     print(block_offset) 
     offset=block_offset+size*n 
     break 
    end 
    fh:seek('cur',-overlap) 
    cur=fh:seek'cur' 
    block=fh:read(size+overlap) 
    n=n+1 
end 

if offset then 
    print('found pattern at', offset, 'after reading',n,'blocks') 
else 
    print('did not find pattern') 
end 

、あなたも説明したトリックを使用することができ、オーバーラップは、パターンがわずか数ブロックと同じよう見過ごさ行くの間で分割がなくなりhere。 Programming in LuaのThis sectionでは、ファイルを読む際のパフォーマンス上の考慮事項について説明しています。

+0

ありがとうございました!それは魅力のように働く。私はセクション21.1まで進んだ。私の質問を投稿する前に、私は21.2.1を逃したので、ヒントのためにありがとう! "#"シンボルの概念にまだ慣れていません。どうやらそれを使用して重複を作成したのですが、その使用法を詳細に説明するセクションと、重複サイズなどの機能は、Luaコードブックにありますか? – Zerobinary99

+0

実際のコードで私の答えを洗い流してくれてありがとう。 – lhf

+0

'# '演算子は文字列の長さ、シーケンスであるテーブル(キーは1からn、穴なし)、または__lenメタメソッドを定義するオブジェクトを返します。文字列の長さは*バイト数であり、必ずしも文字数に等しいとは限りません(UTF-8などと考えてください)。 – jpjacobs

1

行の長さがすべて同じ長さ(4096)でない限り、コードがどのように機能するかはわかりません。

io.linesの代わりに、io.read(4096)のブロックを読み取ります。文字列がブロック内に完全には入っていない場合を処理する必要がある点を除いて、残りのコードはそのまま使用できます。ファイルが行で構成されている場合、Programming in Luaで説明されているトリックは、行境界で終了するブロックを読み取るためにio.read(4096,"*l")を実行することです。ブロック内の文字列については心配する必要はありませんが、ブロックの長さを含めるようにオフセット計算を調整する必要があります。

+0

お返事ありがとうございます!私はプロセスモニタでio.lines-readingの動作を解析し、ファイルが4096byteのチャンクで読み込まれたことを示していたので、これがio.linesの標準値であると仮定しました。あなたは私を真っ直ぐにしている解決策です。再度、感謝します! – Zerobinary99