組み込みクラス: IO編
Fileクラスのスーパークラスなので、IOクラスのメソッドの多くはFileクラスでも使用可能。
IOを開く
Fileの時と同じく、openは第二引数でモードを指定しなければ、readモードとなる。
io = open("text.txt","r+"){ |io| io.write("HelloWorld from Ruby IO.") puts io.write }
IOクラスではコマンドの出力結果を得ることができる。open
メソッドの引数の一番前にパイプを差し込むことで実現できる。
irb(main):002:0> io = open("|ls -a") (irb):2: warning: Insecure world writable dir /home/pyons/.rbenv/versions in PATH, mode 040777 => #<IO:fd 9> irb(main):003:0> io.read => ".\n..\n.bash_history\n.bash_logout\n.bash_profile\n.bashrc\n.bundle\n"
定数STDOUT
を用いれば、標準出力に対して書き込みを行うこともできる。
irb(main):001:0> p STDOUT.write("heloworld") heloworld9 => 9
IOオブジェクトにはreadモードとwriteモードでそれぞれ異なる、IO閉じメソッドが用意されているようだが、今のところ使い方が良く分かっていない。
io = open("text.txt","r+"){ |io| io.write("HelloWorld from Ruby IO.") io.close_write puts io.write }
PS C:\Users\broad\Desktop> ruby .\dir.rb Traceback (most recent call last): 3: from ./dir.rb:33:in `<main>' 2: from ./dir.rb:33:in `open' 1: from ./dir.rb:35:in `block in <main>' ./dir.rb:35:in `close_write': closing non-duplex IO for writing (IOError)
IOからの入力
IO.read
openされたIOから内容をすべて読み込む。また、引数で読み込む長さを指定することもできる。 IOクラスのインスタンスであるioオブジェクトからも実行することが出来る。
p IO.read("text.txt",7)
"HelloWo"
open
メソッドがいきなり出てくる点に戸惑うが、openメソッドはクラスを指定せずにインスタンスが生成される模様。
module function Kernel.#open (Ruby 2.6.0)
io = open("text.txt","r+") p io.read
PS C:\Users\broad\Desktop> ruby .\dir.rb "HelloWorld from Ruby IO."
IO.foreach
IOクラスから一行ずつ読み込み、ブロックに送り込む。
IOクラスのインスタンスからも実行可能だが、その場合each
またはeach_lines
とメソッド名が変わる。
io = open("text.txt","r+") p io.each{ |line| p line } IO.foreach("text.txt"){ |line| p line }
PS C:\Users\broad\Desktop> ruby .\dir.rb "HelloWorld from Ruby IO.\n" "This is test file to check the IO class.\n" "I hope tomorow test will be fine.\n" " " #<File:text.txt> "HelloWorld from Ruby IO.\n" "This is test file to check the IO class.\n" "I hope tomorow test will be fine.\n" " "
一方readlines
はファイルをすべて読み込んで、配列で返す。
irb(main):001:0> io = open("text.txt") => #<File:text.txt> irb(main):002:0> io.readlines => ["HelloWorld from Ruby IO.\n", "This is test file to check the IO class.\n", "I hope tomorow test will be fine.\n", " "]
一行ずつ読み込ませるにはgets
(標準入力も一行の読み込み)やreadline
を使う。
irb(main):004:0> io = open("text.txt") => #<File:text.txt> irb(main):005:0> io.readline => "HelloWorld from Ruby IO.\n" irb(main):006:0> io.gets => "This is test file to check the IO class.\n" irb(main):007:0> io.readline => "I hope tomorow test will be fine.\n" irb(main):008:0> io.gets => " " irb(main):009:0> io.readline Traceback (most recent call last): 5: from C:/Ruby26-x64/bin/irb.cmd:31:in `<main>' 4: from C:/Ruby26-x64/bin/irb.cmd:31:in `load' 3: from C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>' 2: from (irb):9 1: from (irb):9:in `readline' EOFError (end of file reached)
バイトごとに一文字ずつ読み込んで、整数で返すこともできる。
irb(main):006:0> io = open("text.txt","r+") => #<File:text.txt> irb(main):007:0> byte = io.getbyte => 72 irb(main):008:0> byte.chr => "H" irb(main):009:0> byte = io.getbyte => 101 irb(main):010:0> byte.chr => "e"
read_byteというエイリアスも存在する。
一文字ずつの読み込みはgetc
またはread=char
irb(main):011:0> io = open("text.txt","r+") => #<File:text.txt> irb(main):012:0> io.getc => "H" irb(main):013:0> io.getc => "e" irb(main):014:0> io.getc => "l" irb(main):015:0> io.getc => "l" irb(main):016:0> io.getc => "o" irb(main):017:0> io.getc => "W"
each_char
という一文字ずつ読み込んでブロックに渡すメソッドも存在する。
io = open("text.txt","r+") array = [] io.each_char{|chr| array << chr} p array
PS C:\Users\broad\Desktop> ruby .\dir.rb ["H", "e", "l", "l", "o", "W", "o", "r", "l", "d", " ", "f", "r", "o", "m", " ", "R", "u", "b", "y", " ", "I", "O", ".", "\n", "T", "h", "i", "s", " ", "i", "s", " ", "t", "e", "s", "t", " ", "f", "i", "l", "e", " ", "t", "o", " ", "c", "h", "e", "c", "k", " ", "t", "h", "e", " ", "I", "O", " ", "c", "l", "a", "s", "s", ".", "\n", "I", " ", "h", "o", "p", "e", " ", "t", "o", "m", "o", "r", "o", "w", " ", "t", "e", "s", "t", " ", "w", "i", "l", "l", " ", "b", "e", " ", "f", "i", "n", "e", ".", "\n", " "]
EOF(End of File)になったときに挙動はそれぞれメソッドによって異なるが、ここでは省略する。
ここまで入力用の様々なメソッドを見てきたが、今度は出力用メソッドを見てみる。
通常の出力はwrite
であるが、puts
とprint
メソッドは複数の引数をとれる。
io = open("text.txt","r+") array = [] io.puts("Write","Test","From","Ruby") io.each_line{|chr| array << chr} p array
PS C:\Users\broad\Desktop> ruby .\dir.rb ["\n", "This is test file to check the IO class.\n", "I hope tomorow test will be fine.\n", "Write\n", "Test\n", "From\n", "Ruby\n"]
puts
とprint
は正確には挙動が若干異なるようだが、あまり理解できていない。
printfは指定されたフォーマットで文字列を出力する。
irb(main):003:0> STDOUT.printf("%05d","9999") 09999=> nil irb(main):005:0> STDOUT.printf("%08d","9999") 00009999=> nil
また、「putc」というメソッドは「一文字だけの出力」を行うが、 * 整数の引数の場合は最下位のバイトを文字コードとする文字 * 文字列の場合は先頭の一文字 * どちらでもなければ(例:8進数など)to_iメソッドで整数化して文字コードを出す
ことで出力している。
irb(main):002:0> STDOUT.putc("a") a=> "a" irb(main):005:0> STDOUT.putc(65) A=> 65 irb(main):006:0> STDOUT.putc("HelloWorld") H=> "HelloWorld" irb(main):007:0> STDOUT.putc(0o101) A=> 65