2017-04-11 16 views
0

大きなファイルの単純な解析を実行します。 大きなテキストファイルからブロックを選択し、これらのブロックを新しいテキストファイルに書き込もうとしています。私の現在のメソッドは非常にゆっくりと動作します。たとえば :解析のための ファイル:単純な大きなファイルの高速解析

1test 
1111 
2222 
3333 
4444 
1test 
5555 
6666 
2test 
5555 
4444 
3test 
0000 
4test 
9999 
0000 
5test 
3333 
3333 
8test 
2222 
9test 
6666 
11test 
1111 

私は新しいファイル内ら次のデータたい:まもなくで

1test 
1111 
2222 
3333 
4444 
1test 
5555 
6666 
2test 
5555 
4444 
3test 
0000 
4test 
9999 
0000 
5test 
3333 
3333 

、私はソースファイルから特定のブロックを選択しようとしています。

マイコード:

arr = [] 

data = File.read("/path/to/file") 

blocks = ['1test','2test','3test','4test','5test'] 
blocks.each do |block| 

want = data.match(/#{block}(.*)#{block}/m)[0] 
want.each_line do |line| 
    arr << line 
    File.open("/path/to/result/file", 'w') { |file| file.write("#{res.join}") } 
end 

end 

私は私の問題は、私は何度も「欲しい」のデータを読むことだと思います。 「必要な」データの1回のパスで結果ファイルに書き込む方法はありますか?

答えて

3

コード

require 'set' 

def save_blocks(fname_in, fname_out, *blocks) 
    sblocks = blocks.to_set 
    save = false 
    File.open(fname_out, 'w') do |f| 
    File.foreach(fname_in) do |line| 
     lc = line.chomp 
     save = sblocks.include?(lc) if lc =~ /\A\d+test\z/ 
     f.write(line) if save 
    end 
    end 
end 

てみましょう最初のstrが問題に与えられた例の文字列であるテストファイルを作成します。

FNameIn = "test.in" 
FNameOut = "test.out" 
File.write(FNameIn, str) 
    #=> 135 

これを確認できます。

puts File.read(FNameIn) 
1test 
1111 
2222 
... 
3test 
0000 
4test 
... 
11test 
1111 

ここでメソッドを実行します。

save_blocks(FNameIn, FNameOut, "1test", "3test", "5test") 

出力ファイルが正しく書き込まれたことを確認できます。

puts File.read(FNameOut) 
1test 
1111 
2222 
3333 
4444 
1test 
5555 
6666 
3test 
0000 
5test 
3333 
3333 

Iは単にinclude?の動作速度に設定するblocks変換。いずれかのファイルを明示的に閉じる必要はありません。それぞれのブロックが戻ったときに閉じられるためです。

関連する問題