web-dev-qa-db-ja.com

Rubyでファイルを読むための一般的な方法は何ですか?

Rubyでファイルを読むための一般的な方法は何ですか?

たとえば、これが1つの方法です。

fileObj = File.new($fileName, "r")
while (line = fileObj.gets)
  puts(line)
end
fileObj.close

私はRubyが非常に柔軟であることを知っています。各アプローチの利点/欠点は何ですか?

265
dsg
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
246
fl00r

ファイルが長すぎない場合の最も簡単な方法は次のとおりです。

puts File.read(file_name)

実際、IO.readまたはFile.readは自動的にファイルを閉じるので、ブロックとともにFile.openを使用する必要はありません。

295
mckeed

「丸まっている」ファイルには注意してください。それはあなたが一度にファイル全体をメモリに読み込むときです。

問題はそれがうまく拡大できないということです。合理的なサイズのファイルを使ってコードを開発し、それを本番環境に入れると、突然ギガバイト単位のファイルを読み取ろうとしていることに気付き、ホストがメモリの読み取りと割り当てを試みて凍結します。

行ごとのI/Oは非常に高速であり、ほとんどの場合、丸呑みと同じくらい効果的です。実は驚くほど速いです。

私は使うのが好きです。

IO.foreach("testfile") {|x| print "GOT ", x }

または

File.foreach('testfile') {|x| print "GOT", x }

ファイルはIOから継承され、foreachname__はIOにあるため、どちらを使用することもできます。

readname__と「 ファイルを丸呑みにしているのがなぜ良いやり方ではないのか」と比較して大きなファイルを読み込もうとした場合の影響を示すベンチマークがあります。 ".

214
the Tin Man

ファイルを一度に読むことができます。

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

参照先: ファイルAPI および IO API

68
Victor Klos

簡単な方法の1つは、 readlines を使用することです。

my_array = IO.readlines('filename.txt')

入力ファイルの各行は配列のエントリになります。このメソッドはファイルの開閉を処理します。

25
bta
file_content = File.read('filename with extension');
puts file_content;

http://www.Ruby-doc.org/core-1.9.3/IO.html#method- c-read

18
Kumar Immanuel

私は通常これをします:

open(path_in_string, &:read)

これはあなたに文字列オブジェクトとしてあなたに全体のテキストを与えるでしょう。それはRuby 1.9の下でだけ働きます。

9
sawa

your_file.logまたは.txtから最後のn行を返す

path = File.join(Rails.root, 'your_folder','your_file.log')

last_100_lines = `tail -n 100 #{path}`
4
Alex Danko
content = `cat file`

私はこの方法が最も「珍しい」方法だと思います。たぶんそれはちょっとトリッキーなのですが、catがインストールされていればうまくいきます。

0
helloqiu

さらに効率的な方法は、オペレーティングシステムのカーネルにファイルを開き、次にそのファイルから1バイトずつ読み込むように要求することによってストリーミングすることです。 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 }

これについては、この詳細な投稿で読んでください。

AppSignalによるRuby Magic Slurping&Streamingファイル

0