300M超のテキストファイルを読み込ませてIterator.continuallyで処理すると
Iterator.continuallyの動作がどれぐらい大きいファイルまで耐えられるのか確認したく、以下の様なスクリプトを書いてみた。
import java.io.{FileInputStream, InputStreamReader, BufferedReader} val br = new BufferedReader(new InputStreamReader(new FileInputStream(args(0)),"UTF-8")) try{ val it = Iterator.continually(br.readLine).takeWhile(_ != null) println("line count = " + it.foldLeft(0)((c,_) => c+1)) } finally { br.close }
これは動く。itを再利用したいから、it.duplicateをしてみた。
val it = Iterator.continually(br.readLine).takeWhile(_ != null) val (it1, it2) = it.duplicate println("line count = " + it1.foldLeft(0)((c,_) => c+1))
これをすると、OutofMemoryでクラッシュする。
では、itをvariableにしてit1をitに戻してはどうか。大方の予測どおり、itcopyはただの参照なので、二回目ではゼロになってしまう。
val it = Iterator.continually(br.readLine).takeWhile(_ != null) var itcopy = it println("line count = " + itcopy.foldLeft(0)((c,_) => c+1)) itcopy = it println("line count = " + itcopy.foldLeft(0)((c,_) => c+1))
では、TraversableなBufferにしてはどうか。
val it = Iterator.continually(br.readLine).takeWhile(_ != null) val b = it.toBuffer println("line count = " + b.foldLeft(0)((c,_) => c+1)) println("line count = " + b.foldLeft(0)((c,_) => c+1))
これは、toBufferを呼んだ時点でOutOfMemoryでクラッシュ。toList、toArrayも上手くいかない。
おそらく、HeapSizeを増やして実行すればうまくいくかもしれない。