Rubyでファイルを読み取る一般的な方法は何ですか?
たとえば、次の1つの方法があります。
fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
puts(line)
end
fileObj.close
Rubyは非常に柔軟です。各アプローチの利点/欠点は何ですか?
Rubyでファイルを読み取る一般的な方法は何ですか?
たとえば、次の1つの方法があります。
fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
puts(line)
end
fileObj.close
Rubyは非常に柔軟です。各アプローチの利点/欠点は何ですか?
回答:
File.open("my/file/path", "r") do |f|
f.each_line do |line|
puts line
end
end
# File is closed automatically at end of block
上記のようにファイルを明示的に閉じることもできます(ブロックを渡してファイルをopen
閉じます):
f = File.open("my/file/path", "r")
f.each_line do |line|
puts line
end
f.close
foreach
代わりに使用open
し、each_line
ブロックを省きます。
f.each { |line| ... }
そして、f.each_line { |line| ... }
(少なくともRubyの2.0.0で)同じ動作を持っているようです。
ファイルが長すぎない場合の最も簡単な方法は次のとおりです。
puts File.read(file_name)
確かに、IO.read
またはFile.read
自動的にファイルを閉じるのでFile.open
、ブロックで使用する必要はありません。
IO.read
またはFile.read
、ファイルを自動的に閉じることもできます。
「だらしない」ファイルに注意してください。これは、ファイル全体を一度にメモリに読み込むときです。
問題は、適切に拡張できないことです。適切なサイズのファイルを使用してコードを開発し、それを本番環境に配置すると、ギガバイト単位のファイルを読み取ろうとしていることがわかり、メモリを読み取って割り当てようとしているときにホストがフリーズします。
行単位のI / Oは非常に高速であり、ほとんど常に丸呑みと同じくらい効果的です。実際には驚くほど高速です。
私は使いたい:
IO.foreach("testfile") {|x| print "GOT ", x }
または
File.foreach('testfile') {|x| print "GOT", x }
ファイルはIOを継承しforeach
、IO内にあるため、どちらでも使用できます。
「ファイルを「スラッピング」するのが良い習慣ではないのはなぜですか?」で、行ごとのread
I / Oを介して大きなファイルを読み取ろうとすることの影響を示すいくつかのベンチマークがあります。
あなたは一度にすべてのファイルを読むことができます:
content = File.readlines 'file.txt'
content.each_with_index{|line, i| puts "#{i+1}: #{line}"}
ファイルが大きい場合、または大きい場合は、通常、1行ずつ処理することをお勧めします。
File.foreach( 'file.txt' ) do |line|
puts line
end
ただし、ファイルハンドルへのアクセスが必要な場合や、読み取りを自分で制御する場合があります。
File.open( 'file.txt' ) do |f|
loop do
break if not line = f.gets
puts "#{f.lineno}: #{line}"
end
end
バイナリファイルの場合は、次のようにnil-separatorとブロックサイズを指定できます。
File.open('file.bin', 'rb') do |f|
loop do
break if not buf = f.gets(nil, 80)
puts buf.unpack('H*')
end
end
最後に、たとえば複数のファイルを同時に処理する場合など、ブロックなしで実行できます。その場合、ファイルは明示的に閉じる必要があります(@antinomeのコメントに従って改善されています)。
begin
f = File.open 'file.txt'
while line = f.gets
puts line
end
ensure
f.close
end
while
代わりにloop
を使用ensure
して、例外が発生した場合でもファイルが確実に閉じられるようにすることをお勧めし ます。このように(セミコロンを改行で置き換えbegin; f = File.open('testfile'); while line = f.gets; puts line; end; ensure; f.close; end
ます):。
file_content = File.read('filename with extension');
puts file_content;
私は通常これを行います:
open(path_in_string, &:read)
これにより、テキスト全体が文字列オブジェクトとして提供されます。Ruby 1.9でのみ動作します。
さらに効率的な方法は、オペレーティングシステムのカーネルにファイルを開いてもらい、ファイルからバイトを少しずつ読み取ってストリーミングする方法です。Rubyで1行ごとにファイルを読み取る場合、データはファイルから512バイトずつ取得され、その後「行」に分割されます。
ファイルのコンテンツをバッファリングすることにより、ファイルを論理チャンクに分割する際のI / O呼び出しの数が削減されます。
例:
このクラスをサービスオブジェクトとしてアプリに追加します。
class MyIO
def initialize(filename)
fd = IO.sysopen(filename)
@io = IO.new(fd)
@buffer = ""
end
def each(&block)
@buffer << @io.sysread(512) until @buffer.include?($/)
line, @buffer = @buffer.split($/, 2)
block.call(line)
each(&block)
rescue EOFError
@io.close
end
end
それを呼び出して、:each
メソッドにブロックを渡します。
filename = './somewhere/large-file-4gb.txt'
MyIO.new(filename).each{|x| puts x }
詳細については、この詳細な投稿をご覧ください。