添付ライブラリ: テキスト編

StringIOと呼ばれるクラスは、インスタンスの生成時に与えられた文字列やputsで与えらた文字列を「バッファ(変数)」に格納し、またバッファに入った文字列をgetsreadlineで読み込むことが出来る。

バッファと聞いて、特殊な仕組みが裏にあると思いきや、文字列の変数のことらしい。 それぞれ、Dirクラスのように読み込みモード、書き込みモード、読み書きモードなどが存在する。

StringIO.newインスタンスを生成できるが、newに代わって openを利用すると、ブロック内だけで、インスタンスの操作が可能になる。インスタンスの内容はブロックの一番最後の評価に書き換わる。

[16] pry(main)> sio = StringIO.open "HelloWorld" do |io|
[16] pry(main)*   "Yeah"  
[16] pry(main)* end  
=> "Yeah"
[17] pry(main)> p sio
"Yeah"
=> "Yeah"

一方バッファへの書き込みは一文字書き込みの putcと文字列に改行を付加して書き込むputsと改行を付加しない`print、フォーマットに従って書き込みを行うprintfがある。

putsは配列が引数に指定された場合は、各配列を連結して、それぞれに改行を付与する。

[18] pry(main)> sio = StringIO.new
=> #<StringIO:0x00007fffcb3909e0>
[19] pry(main)> sio.puts "Hey siri"
=> nil
[20] pry(main)> sio.string
=> "Hey siri\n"
[21] pry(main)> sio.putc "ABCD"
=> "ABCD"
[22] pry(main)> sio.string
=> "Hey siri\nA"
[23] pry(main)> sio.string = ""
=> ""
[24] pry(main)> sio.putc "ABCD"
=> "ABCD"
[25] pry(main)> sio.string
=> "A"
[26] pry(main)> sio.puts(["tokyo","shinagawa","shinyokohama"])
=> nil
[27] pry(main)> p sio
#<StringIO:0x00007fffcb3909e0>
=> #<StringIO:0x00007fffcb3909e0>
[28] pry(main)> sio.string
=> "Atokyo\nshinagawa\nshinyokohama\n"

一方、バッファからの読み込みはreadreadcharreadlineがある。

readの場合は引数に指定した数字だけバッファからの読み取りを行い、ポインタはその分だけ先に進む。

[32] pry(main)> sio.string
=> "Melbourne Australia VIC\n"
[33] pry(main)> sio.read 3
=> nil
[36] pry(main)> sio.pos = 0
=> 0 #ポインタの移動を行う
[37] pry(main)> sio.read(3)
=> "Mel"
[38] pry(main)> sio.read(1)
=> "b"
[39] pry(main)> sio.read(1)
=> "o"
[40] pry(main)> sio.read(10)
=> "urne Austr"
[41] pry(main)> sio.read(20)
=> "alia VIC\n"
[42] pry(main)> sio.read
=> ""
[43] pry(main)> sio.read(100)
=> nil

また、第二引数に変数が指定されている場合、その変数に読み取った文字が格納される。

[48] pry(main)> var = ""
=> ""
[49] pry(main)> sio.read(10,var)
=> "Melbourne "

さらに引数を省略すれば、ポインタの現在の位置から末尾までの文字が読み取られる。

[49] pry(main)> sio.read(10,var)
=> "Melbourne "
[50] pry(main)> sio.read()
=> "Australia VIC\n"

ポインタが末尾まで到達しているのに、引数に数字を指定するとnilが返ってくるが、この状態で引数を省略すると 空文字列になる。

[51] pry(main)> sio.read()
=> ""

getcとreadcharはどちらも同じ、「一文字読み取り」のメソッドだが、 readcharに限っては末尾まで到達すると、例外が発生する。一方、getcの場合は空文字列ではなくnilとなる。

getsや```readline````の場合は一行単位の読み取りを行う。末尾に到達したときの挙動はreadlineがreadcharと同じく例外である。

ポインタの移動はDirクラスのファイルポインタ移動と似ている。 posのほかにオフセットで指定した場所からの距離を数値で指定して移動することもできる。

[3] pry(main)> sio.string = "ABCDEFGHI"
=> "ABCDEFGHI" 
[4] pry(main)> sio.seek(3,IO::SEEK_SET)
=> 0
[5] pry(main)> sio.read
=> "DEFGHI"

この他にもオフセットはIO::SEEK_CURIO::SEEK_ENDが用意されている。