S-JIS[2011-02-27/2011-08-31] 変更履歴
Scalaでは、テキストファイルを読み込むのにscala.io.Sourceオブジェクトを使用する。
|
テキストファイルを読み込むにはfromFile()メソッドを使用する。(Scala2.8)
import scala.io.Source
val s = Source.fromFile("C:/temp/abc.txt") try { for (line <- s.getLines) { println(line) } } finally { s.close }
fromFile()の第2引数でファイルのエンコーディング(文字コード)を指定することも出来る。
val s = Source.fromFile("C:/temp/abc.txt", "MS932")
(ファイル名を指定するときに"""を使うとWindowsのパス区切りに「\」が使いやすいが、uで始まるファイル名やディレクトリー名でハマるので、過信はしない方がいい)
fromFile()で返されるSource(実際はBufferedSource)は、Char(文字)の並び。
getLines()メソッドを呼び出すと行毎の文字列(String)の並びになる。
SourceおよびgetLines()で返されるイテレーターは、一度しか使えない(繰り返し使うことは出来ない)。
scala> val s = Source.fromFile("C:/temp/abc.txt")
s: scala.io.BufferedSource = non-empty iterator
scala> s.isTraversableAgain
res1: Boolean = false
scala> s.size
res2: Int = 2395
scala> s.size
res3: Int = 0
scala> s.getLines.foreach{ println(_) }
←何も出ない
sizeメソッドの内部実装は、全てのデータを読み込んで文字数を数えるようになっている。
全て読み込んでしまうので、イテレーターはファイルの末尾を指す状態になり、再度sizeを呼び出しても(もう読み込めるものが無いので)0を返す。
この状態から文字列を取得しようとしても無理(何も返ってこない)。
したがって、読み込んだ結果を繰り返し使用したい場合はtoListメソッド等を使って変換しておく。
val s = Source.fromFile("C:/temp/abc.txt") val list = try s.getLines.toList finally s.close
Scala2.9.0のREPLでは、Sourceの生成とその後の操作を2行に分けて実行すると、結果が空になる。[2011-06-05]
Scala2.9.1-finalで直った。[2011-08-31]
Scala | 備考 |
---|---|
scala> val s = Source.fromFile("C:/temp/a2.txt")
s: scala.io.BufferedSource = non-empty iterator
scala> val r = s.getLines.toList
r: List[String] = List()
|
2行に分けて実行すると、結果が空。 |
scala> val s = Source.fromFile("C:/temp/a2.txt");val r = s.getLines.toList
s: scala.io.BufferedSource = empty iterator
r: List[String] = List(aaa, aa)
scala> val r = Source.fromFile("C:/temp/a2.txt").getLines.toList
r: List[String] = List(aaa, aa)
|
1行で実行すると大丈夫。 |
scala> val s = Source.fromFile("C:/temp/a2.txt")
s: scala.io.BufferedSource = non-empty iterator
scala> val r = s.getLines.toList
r: List[String] = List(aaa, aa)
|
Scala2.8.1-final・2.9.1-finalだと大丈夫。[/2011-08-31] |