Elixirでファイルを読んだり書いたり

昨日のディレクトリ操作に引き続いて、本日はElixirでファイル入出力をやってみます。

簡単な読み書き

単純に読み込む/書き込むだけならものすごく簡単で、以下のように出来ます。

iex> File.write "test.txt", "hello"
:ok
iex> File.read "test.txt"
{:ok, "hello"}

iex> File.write "test.txt", " world", [:append]
:ok
iex> File.read "test.txt"
{:ok, "hello world"}

一回目の書き込みが通常の上書き的な書き込み、二回目の書き込みが追記書き込みになっています。 File.writeの第三引数にオプションを渡すわけですね。使えるオプションについては後述。

ファイルハンドラを使った読み書き

一般的なopenしてwriteして…って流れでも読み書きが出来ます。以下のような感じ。

iex> File.write "test.txt", "はろーわーるど"
:ok

iex> {:ok, fp} = File.open "test.txt"
{:ok, #PID<0.100.0>}

iex> IO.binread fp, 3
"は"

iex> File.close fp
:ok

デフォルトでは読み込みモード、バイナリモード?で開かれるようです。 IO.binreadの第二引数はバイト数です。3文字読みたかったのに1文字しか返って来ませんでした。

ファイルがutf-8で保存されているなら、utf-8モードが使えます。

iex> {:ok, fp} = File.open "test.txt", [:utf8]
{:ok, #PID<0.100.0>}

iex> IO.read fp, 3
"はろー"
iex> IO.read fp, 4
"わーるど"
iex> IO.read fp, 1
:eof

iex> File.close fp
:ok

IO.binreadではなくてIO.readになりました。ちゃんと文字数で指定出来ています。 ファイルの終了まで行ったら:eofが返るのもポイントですね。

書き込みも何の捻りもなく以下のように行ないます。

iex> {:ok, fp} = File.open "test.txt", [:write, utf8]
{:ok, #PID<0.100.0>}

iex> IO.binwrite fp, "はろー"
:ok

iex> File.close fp
:ok

iex> File.read "test.txt"
{:ok, "はろー"}

openするときにオプションに:writeを渡すだけです。

オプション

:read:writeはそのまんま読み込みモード/書き込みモードです。 両方指定すると読み書き両方出来るようになります。 :readを指定しているときは存在しないとエラーに、:writeを指定しているときは存在しなければ作るようです。

:appendを指定すると追記書き込みになります。上でちょこっと使ったやつです。 存在しない場合は新規作成になります。

:exclusiveオプションを:writeと同時に使うと、ファイルが存在するとエラーが返るようになります。 新規作成だけを認める場合に使うオプションですね。

:char_list:utf8を使うと読み込んだときに返る型を決められるようです。 何も付けないとbinaryで返るようになっています。 エンコーディングについては:utf16utf32:big:littleなど、色々オプションがあるようです。

:compressedを付けるとファイルがgzipで圧縮されるようになります。 圧縮レベルなどのオプションもあるのかもしれませんが、見付けられませんでした。

:delayed_write:syncを付けると、書き込みを即座に行なうかバッファするかを選べます。 デフォルトでは:syncのようです。細かく沢山書き込むときは:delayed_writeにしておくのが賢いのかも?


参考: