sbtのIOライブラリsbt-ioを使ってみる

ScalaのIOライブラリは何を使うのがいいのかなぁ、ということで前回はscalaz-effectを試してみたのですが、今回はsbtのIOライブラリを試してみました。sbtで使用されているものですが、単体のライブラリとしても使用することができます。

sbt-ioを使用するにはbuild.sbtに以下の依存関係を追加します。

libraryDependencies += "org.scala-sbt" %% "io" % "1.0.0-M3"

sbt.io.IOオブジェクトに様々な便利メソッドが用意されています。

import sbt.io._
import java.io._

// ファイルから文字列として読み込み
val result1: String = IO.read(new File("build.sbt"), IO.utf8)
// ファイルからバイト配列として読み込む
val result2: Array[Byte] = IO.readBytes(new File("test.txt"))
// ストリームからバイト配列として読み込み
val result3: Array[Byte] = IO.readBytes(new FileInputStream("text.txt"))
// ファイルから行ごとのリストとして読み込み
val result4: List[String] = IO.readLines(new File("test.txt"), IO.utf8)

// ファイルに文字列を書き込み
IO.write(new File("test.txt"), "Hello World", IO.utf8)
// ファイルにバイト配列を書き込み
IO.write(new File("test.txt"), "Hello World".getBytes(IO.utf8))
// ファイルに行ごとのリストを書き込み
IO.writeLines(new File("test.txt"), List("Hello", "World"), IO.utf8)

大きなファイルを読み込むときはIO.readerBufferedReaderを生成し、それをIO.foreachLineIO.foldLinesなどのメソッドで1行ずつ処理することもできます。

IO.reader(new File("test.txt"), IO.utf8){ reader =>
  IO.foreachLine(reader){ line =>
    println(line)
  }
}

入出力だけでなく、ファイル・ディレクトリ操作のためのメソッドもあります。

// ファイルがなければ作成
IO.touch("test.txt")
// ファイルをコピー
IO.copyFile(new File("test.txt"), new File("test.bak"))
// ファイルを移動
IO.move(new File("test.txt"), new File("test.bak"))
// ディレクトリをコピー
IO.copyDirectory(new File("src"), new File("target"))
// ファイルまたはディレクトリを削除
IO.delete(new File("test.txt"))

この他にもファイルを圧縮・展開するためのメソッドや、一時ファイル・一時ディレクトリを使用した処理を行うためのメソッド、URLのリソースをダウンロードして指定したファイルに保存するメソッドなど、様々な便利メソッドが用意されています。利用可能なメソッドScaladocを参照するといいです。

なお、ローンパターン的なものはIO内部では使用されているのですが、外部からは利用できないようになっています。自分でストリームをゴリゴリ触るようなケースではローンパターンが欲しくなると思うのでちょっと残念です。また、エラー処理に関しては例外が飛ぶようになっていますが、内部的にjava.io.Fileメソッドで処理しているようなものはメソッドの戻り値が無視されているケースもあり、厳密なエラーハンドリングが必要なケースでは使いにくいかもしれません。

sbt-ioは完璧とはいえないものの、便利かつ簡単に利用できるので、カジュアルな用途であればこれで十分なのではないかと思います。

追記:0.13.9ならローンパターン使えるそうです。