RubyのFileとIOを使うと、ファイルを読み書きできます。使い方の備忘録です。
公式リファレンス
- File: https://docs.ruby-lang.org/ja/2.3.0/class/File.html
- IO: https://docs.ruby-lang.org/ja/2.3.0/class/IO.html
準備
FileもIOもRubyの組み込みライブラリなのでrequireは不要です。なので特に準備はありません。
ファイルを新規作成する
ファイルを新規作成するにはFile.openの第二引数に"w"か"w+"を指定してファイルを開きます。ファイル”example“を作ってみます。
File.open( "example" , "w" ) { |f|
}
ルート直下にファイルが作られたかと思います。もう一回新規作成すると現在のファイルの中身は消えて、空のファイルができます。
ファイルを開く
ファイルを開くには、File.openの第二引数にrやwやaを指定します。
- “r” : 読み込み専用で開く。デフォルト
- “r+” : 読み書きモードで開く。書き込むと
先頭に追加されます。 - “a” : 書き込み専用モードで開く。書き込むと
終端に追加されます。 - “a+” : 読み書きモードで開く。 書き込むと
終端に追加される。 - “w” : 書き込み専用モードで開く。
ファイルの内容は空になります。 - “w+” : 読み書きモードで開く。
ファイルの内容は空になります。
いずれも”b”を追加で指定すると、バイナリモードになります。
File.openは2種類の書式があります。
戻り値を変数で受けた場合は、自動的にファイルがクローズしないので、自分でcloseする必要があります。
f = File.open( "example" ) f.close
戻り値をブロックで受けた場合は、ブロックを抜けると自動的にファイルがクローズします。
File.open( "example" ) { |f|
}
存在しないファイルを開くと?
存在しないファイルを”r“や”r+“モードで開くとどうなるのでしょうか。
begin
File.open( "nonexist" ) { |f|
}
rescue => e
p e
end
Errno::ENOENTが発生するようです。
#<Errno::ENOENT: No such file or directory @ rb_sysopen - nonexist>
ファイルを読む
ファイルの内容を読むシンプルな方法はIO.readを使うことです。現在の位置からEOFまでの内容がすべて返ってきます。
File.open( "example" ) { |f|
f.read
}
読み込み系のメソッドには次のようなものがあります。
1文字読み込む
IO.getcかIO.readcharを使います。getcはEOF到達時にnilを返しますが、readcharはEOFErrorが発生します。
File.open( "example" ) { |f|
p f.getc
p f.readchar
}
"h" "e"
1行読み込む
IO.getsかIO.readlineを使います。getsはEOF到達時にnilを返しますが、readlineはEOFErrorが発生します。
File.open( "example" ) { |f|
p f.gets
p f.readline
}
"hello world!\n" "hello world!\n"
各行を読み込む
IO.each_lineを使います。現在位置から一行ずつブロックに引数を渡して処理します。
File.open( "example" ) { |f|
f.each_line {|line|
p line
}
}
"hello world!\n" "hello world!\n" "hello world!\n"
全行を読み込む
IO.readlinesを使います。各行が配列で返ります。
File.open( "example" ) { |f|
p f.readlines
}
["hello world!\n", "hello world!\n", "hello world!\n"]
書き込み専用モードでファイルを読むと?
“w“や”a“モードでファイルを開いたときにファイルを読むとどうなるのでしょうか。
begin
File.open( "example", "w" ) { |f|
f.read
}
rescue => e
p e
end
IOErrorが発生するようです。
#<IOError: not opened for reading>
ファイルに書く
ファイルへ書き込むにはIO.writeを使います。改行は\nです。
File.open( "example", "w" ) { |f|
f.write "hello world!\n"
}
読み込み専用モードでファイルへ書くと?
読み込み専用モードでwriteしてみます。
File.open( "example" ) { |f|
f.write "hello world!\n"
}
IOErrorが発生するようです。
#<IOError: not opened for writing>
画像ファイルを読む
画像のようなバイナリデータのファイルを読むときは、バイナリモード”b“を指定して開きます。
File.open( "example.jpg", "rb" ) { |f|
p f.read
}
画像ファイルとして書き出す
ネットワークから取得した画像データなどのバイナリデータをファイルに書き出す場合は、バイナリモード”b“を指定して開きます。
OpenURIで画像をダウンロードして、ファイルとして保存する例です。
require 'open-uri'
uri = 'http://example.com/foo.jpg'
open(uri) { |io|
File.open(name, "wb") { |f|
f.write io.read
}
}
バイナリモードでファイルを開いていないと、次のような感じでEncoding::UndefinedConversionErrorが発生したりします。
#<Encoding::UndefinedConversionError: "\xFF" from ASCII-8BIT to UTF-8>