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>