「Ioが面白い」と言って3月に集中的に学習してブログにも書きまくってましたが、一段落ついてみると積極的に使う場面がなくてなんとなく放置。そのあいだにLuaを使うことになったり、本業のC++をやっていたりとしたわけですが。なにやら。アクセスログを見ていると割と定期的にIoの記事を見にきてくださっている方がいらっしゃるようで。それを見ると、新しいネタ提供できてないのが申し訳ないなーという思いがわいてきて、同時に、Ioでまだ学び足んないところあるんだよなーと考えていたことが思い起こされて。
そんなこんなで、Io再起動です。
今回は。プログラミングする上でほぼ必須と言える機能、ファイルの入出力について。
基本の操作
ファイル操作の基本は、(1)File
オブジェクトのクローンを作る、(2)クローンにファイルパスをセットする、(3)ファイルを開く、(4)ファイルの内容を操作する、(5)ファイルを閉じる、という流れになります。
実例。
file := File clone // クローンを作る file setPath("foo.txt") // ファイルパスをセットする file open // ファイルをオープンする file write("hoge\n", "fuga\n", "uhyo\n") // ファイルに文字列を書き出す file rewind // アクセス位置をファイルの戦闘に巻き戻す while(line := file readLine, // ファイル内の文字列を行単位で読み込む line println ) file close // ファイルを閉じる
実行結果。
$ io sample0.io hoge fuga uhyo
この操作ではファイルが存在しないばあい、新しくファイルが作成されました。すでにファイルが存在していて内容がある場合はどうなるか。
すでに内容があるファイルを用意します。
$ cat foo.txt HOGE FUGA UHYO HOGE FUGA UHYO
実行結果。
$ io sample0.io hoge fuga uhyo HOGE FUGA UHYO
ファイルのサイズはそのままで操作をした部分だけが書き換えられているのがわかります。
ファイルのクローン、パスのセット、ファイルのオープンまではセットで扱うことが多いので、メソッドチェーンにして次のように書くことが多いようです。
file := File clone setPath("foo.txt") open
さらに。クローンとパスのセットをセットにしたwith
メソッドを使うとさらに見やすくなります。
file := File with("foo.txt") open
openFor〜
open
メソッドはファイルの書き換え(ファイルがないばあいは作成して書き込み)をおこないましたが、読み込みのみをしたいばあいや、既存の内容を破棄してから書き込みをしたいばあいがあります。そのばあいはopenFor
から始まるメソッドを使います。
メソッド名 | 操作内容 | 対象ファイルが存在しない場合 |
---|---|---|
openForAppending |
ファイルの末尾に追加する | 例外を発生させる |
openForReading |
ファイルの内容を読み出す | 例外を発生させる |
openForUpdating |
ファイルの先頭から書き込む | ファイルを作成する |
openForUpdating
メソッドは実質open
メソッドと同じ動作をします。
file := File with("foo.txt") openForUpdating file write("foo\n", "bar\n", "baz\n") file rewind while(line := file readLine, line println ) file close
実行結果。
$ cat foo.txt AAA BBB CCC DDD EEE FFF $ io sample3.io foo bar baz DDD EEE FFF
既存のファイルの内容をすべて破棄して一新したい場合はオープンする前にremove
メソッドで既存のファイルを破棄するようにします。remove
はオブジェクト自身を返すのでメソッドチェーンに組み込むことができます。
file := File with("foo.txt") remove openForUpdating file write("foo\n", "bar\n", "baz\n") file rewind while(line := file readLine, line println ) file close
$ cat foo.txt AAA BBB CCC DDD EEE FFF $ io sample4.io foo bar baz
バイト単位の読み出し、行単位の読み出し
foreach
メソッドを使うとバイト単位で、foreachLine
メソッドを使うと行単位で、ファイルを読み出すことができます。インデクスの値をとる第1引数は省略可能です。
実装。
file := File with("foo.txt") openForReading file foreach(i, v, writeln(i, ":", v) ) file close
実行結果。
$ cat foo.txt foo bar baz $ io sample5.io 0:102 1:111 2:111 3:10 4:98 5:97 6:114 7:10 8:98 9:97 10:122 11:10
実装。
file := File with("foo.txt") openForReading file foreachLine(i, v, writeln(i, ":", v) ) file close
実行結果。
$ cat foo.txt foo bar baz $ io sample6.io 0:foo 1:bar 2:baz
中身丸ごと読み込み
ファイルの中身をごっそりメモリ上に読み込む方法は(少なくとも)3種類あります。
メソッド名 | 操作内容 | 標準入力に対して |
---|---|---|
contents |
ファイルの内容をひとつの文字列(バイト列)として返す | 操作可能 |
asBuffer |
ファイルの内容をひとつの文字列(バイト列)として返す | 不可 |
readLines |
改行で分離した文字列のリストを返す | 操作可能 |
標準入力を対象としない場合、contents
とasBuffer
はほぼ同じと考えてよいようです。
標準入出力
標準入出力はFile
に定義されているメソッドで対応するオブジェクトを取得できます。これらはFile
のクローンなので、File
で定義されているメソッドを利用できます。
メソッド名 | 内容 |
---|---|
standardInput |
標準入力 |
standardOutput |
標準出力 |
standardError |
標準エラー出力 |