もやもやエンジニア

IT系のネタで思ったことや技術系のネタを備忘録的に綴っていきます。フロント率高め。

Elixir 入門 その11 - IO and the file system

The IO module

# 標準出力
iex> IO.puts "hello world"
hello world
:ok

# 標準入力
iex> IO.gets "yes or no? "
yes or no? yes
"yes\n"

# :stderrをarg1に与えると出力先が標準エラーになる
iex> IO.puts :stderr, "hello world"
hello world
:ok

The File module

  • FileモジュールはファイルのI/OのためのモジュールでUnixのファイル操作系コマンドに相当する関数が多数用意されている。
  • ファイルはUTF-8をデフォルトで扱う。
# ファイルを書き込みモードで開く。arg1がファイル名、arg2がモード
# モードの参照 
# [http://elixir-lang.org/docs/v1.0/elixir/File.html#t:mode/0]

iex> {:ok, file} = File.open "hello", [:write]
{:ok, #PID<0.47.0>}

# 書き込み
iex> IO.binwrite file, "world"
:ok

# Close
iex> File.close file
:ok

# 読み込み。存在しないファイルを指定すると :error が返る
iex> File.read "hello"
{:ok, "world"}

iex> File.read "hoge"
{:error, :enoent}

# File.read! を使うこともできる。この場合はtupleで返らず、ファイルの中身をそのまま取得する
iex> File.read! "hello"
"world"

# read!の場合は例外が返る
iex> File.read! "hoge"
** (File.Error) could not read file unknown: no such file or directory

# パターンマッチを使うとハンドルしやすい。ハンドルの必要が無ければread!を使えばよい。
case File.read(file) do
  {:ok, body}      -> # do something with the `body`
  {:error, reason} -> # handle the error caused by `reason`
end

The Path module

iex> Path.join("foo", "bar")
"foo/bar"

iex> Path.expand("~/hello")
"/Users/rei_m/hello"

Processes and group leaders

# File.openを呼ぶと :ok と PIDのtupleが返る。FileモジュールはProcessモジュールと共に動いていることがわかる。
iex> {:ok, file} = File.open "hello", [:write]
{:ok, #PID<0.47.0>}

# プロセスIDから読み込むこともできる
iex> IO.read(pid, 2)
"he"
  • Erlang VM複数の同じネットワーク内の異なるノード間でファイルのread/writeを共有するための仕組みとして特別なプロセスであるgroup leaderを提供している
  • :stdioにメッセージを送る時などは実際にはgroup leaderに送っている
  • group leaderはプロセス毎に設定できる。
iex> IO.puts :stdio, "hello"
hello
:ok

iex> IO.puts Process.group_leader, "hello"
hello
:ok