2009-07-07 10 views
6

私はプログラミングに慣れていないので、やさしくしてください。私はライブラリデータベースの.datファイルからIBSN番号を抽出しようとしています。私は動作するコードを書いていますが、それは180MBのファイルの約半分を検索しているだけです。ファイル全体を検索するにはどのように調整できますか?または、どのように私は管理可能なチャンクにdatファイルを分割するプログラムを書くことができますか?Rubyで大きなファイルを処理するにはどうすればよいですか?

編集:ここに私のコードです:あなたは現代のオペレーティングシステム上でプログラミングしていると、コンピュータが(512megsを言う)十分なメモリを持っている場合

export = File.new("resultsfinal.txt","w+") 

File.open("bibrec2.dat").each do |line| 
    line.scan(/[a]{1}[1234567890xX]{10}\W/) do |x| 
    export.puts x 
    end 
    line.scan(/[a]{1}[1234567890xX]{13}/) do |x| 
    export.puts x 
    end 
end 
+0

@ zed_0xff:Yoann Le Toucheのアプローチは、ファイル全体をメモリに読み込まなかった。 –

答えて

-2

、Rubyはファイル全体をメモリに読み込む何の問題もないはずです。

典型的な32ビットOSで約2ギガバイトのワーキングセットを取得すると、一般的に問題が発生します。

+0

Vistaで4GBの空き容量があるのか​​どうか分かりました。また、エラーは発生せず、不完全な結果しか得られません。 –

+0

私は彼がデータがあなたの記憶のサイズではなく4GBであることを意味すると信じています。 32ビットオペレーティングシステムでは約3.5GB以上のRAMを処理できないため、64ビットVistaを使用している場合を除き、4GBのRAMを自由に使用できます。データセットが180MBしかない場合は、問題がコード内になければなりません。スクリプトを投稿しますか? – jkeys

+0

問題ありません、明日投稿します。どうもありがとう。 –

1

パフォーマンスの問題については、ファイルサイズについて特に心配するものはありません.180MBで問題が発生しないはずです。スクリプトを実行しているときにメモリ使用はどうなりますか?

しかし、あなたの正規表現はあなたが望むことをしているかどうかはわかりません。これは、例えば:

  • 1 "A":

    /[a]{1}[1234567890xX]{10}\W/ 
    

    は(私が思う)これを行います。あなたは本当に "a"にマッチしたいですか?その場合、「[a] {1}」ではなく、「a」で十分です。

  • 正確に10(数字や "×" または "X")
  • のシングル "非単語" 文字すなわちAZない、AZ、0-9または

を強調するのカップルがあります。 ISBNマッチャーherehereがありますが、書籍の裏表紙に書かれているような形になっているようですが、入力ファイルがその書式の一部を取り除いたと思います。

+0

元のデータファイルはISBNをその形式に再フォーマットしました。なぜそれが完了したのか分かりません!ちょうど「a」と書いてもいいですよ。 –

4

例外が実際に読み取りブロックにあるかどうかを確認するために、例外をキャッチしようとする必要があります。

私は既に同じ構文を使ってスクリプトを作成して、実際の大きなファイルを8GBまで問題なく検索しています。

export = File.new("resultsfinal.txt","w+") 

File.open("bibrec2.dat").each do |line| 
    begin 
    line.scan(/[a]{1}[1234567890xX]{10}\W/) do |x| 
     export.puts x 
    end 
    line.scan(/[a]{1}[1234567890xX]{13}/) do |x| 
     export.puts x 
    end 
    rescue 
    puts "Problem while adding the result" 
    end 
end 
2
file = File.new("bibrec2.dat", "r") 
while (line = file.gets) 
    line.scan(/[a]{1}[1234567890xX]{10}\W/) do |x| 
    export.puts x 
    end 
    line.scan(/[a]{1}[1234567890xX]{13}/) do |x| 
    export.puts x 
    end 
end 
file.close 
3

主なものは、クリーンアップし、パフォーマンス上の利点のための正規表現を組み合わせることです。また、ファイルのブロック構文を使用して、fdが正しく閉じられていることを確認する必要があります。それぞれがメモリにファイル全体をロードしませんファイル#、それは一度に1行ん:あなたは

File.open("resultsfinal.txt","w+") do |output| 
    File.open("bibrec2.dat").each do |line| 
     output.puts line.scan(/a[\dxX]{10}(?:[\dxX]{3}|\W)/) 
    end 
end 
1

File#truncateIO#seekを使用してに見て、二分探索型のアルゴリズムを採用することができます。 #truncateが破壊的な場合がありますので、を複製してくださいファイル(これは面倒です)。

middle = File.new("my_huge_file.dat").size/2 
tmpfile = File.new("my_huge_file.dat", "r+").truncate(middle) 
# run search algoritm on 'tmpfile' 
File.open("my_huge_file.dat") do |huge_file| 
    huge_file.seek(middle + 1) 
    # run search algorithm from here 
end 

コードは非常に、テストされていない脆く、不完全です。しかし、私はそれがあなたにビルドオフのプラットフォームを与えることを願っています。

+0

ファイルの途中でファイルを分割するとどうなりますか? ;) – fenec

関連する問題