私はこれのほとんどをプレイコードを読んで得たので、誤解しているかもしれませんが、私が見ることができるものから:Enumerator.fromFile
function(Iteratee.scala [ docs] [src])は列挙子を作成します。ファイルからの読み取りが完了したときのIterateeの出力。Iteratee[Byte, Byte]
Input.EOF
プレイによると!リンクしたドキュメントの例では、列挙子の最後にInput.EOF(Enumerator.eofのエイリアス)を手動で追加することになっています。Input.EOFをファイルのバイト配列の最後に自動的に追加することが、返されるファイルが1つだけになる理由だと思います。
Play Consoleでの同等の簡単な例は、次のとおりです。
scala> val fileContent1 = Enumerator("blah") andThen Enumerator.eof
fileContent1: play.api.libs.iteratee.Enumerator[java.lang.String] = play.api.libs.iteratee.Enumerator$$anon$23@2256deba
scala> val fileContent2 = Enumerator(" and more blah") andThen Enumerator.eof
fileContent2: play.api.libs.iteratee.Enumerator[java.lang.String] = play.api.libs.iteratee.Enumerator$$anon$23@7ddeef8a
scala> val it: Iteratee[String, String] = Iteratee.consume[String]()
it: play.api.libs.iteratee.Iteratee[String,String] = play.api.libs.iteratee.Iteratee$$anon$18@6fc6ce97
scala> Iteratee.flatten((fileContent1 andThen fileContent2) |>> it).run.value.get
res9: String = blah
修正は、まだ試していませんが、数レベル深くして関数を直接使用し、連結するすべてのファイルが読み取られるまでsEnumerator.fromCallback
を返し続けるカスタムレトリバー関数を渡すことです。デフォルトとは何か、およびそれを変更する方法についてはArray[Byte]
、関数の実装を参照してください。fromStream
これを行う方法の例(から適応Enumerator.fromStream
):
def fromFiles(files: List[java.io.File], chunkSize: Int = 1024 * 8): Enumerator[Array[Byte]] = {
val inputs = files.map { new java.io.FileInputStream(_) }
var inputsLeftToRead = inputs
Enumerator.fromCallback(() => {
def promiseOfChunkReadFromFile(inputs: List[java.io.FileInputStream]): Promise[Option[Array[Byte]]] = {
val buffer = new Array[Byte](chunkSize)
(inputs.head.read(buffer), inputs.tail.headOption) match {
case (-1, Some(_)) => {
inputsLeftToRead = inputs.tail
promiseOfChunkReadFromFile(inputsLeftToRead)
}
case (-1, None) => Promise.pure(None)
case (read, _) => {
val input = new Array[Byte](read)
System.arraycopy(buffer, 0, input, 0, read)
Promise.pure(Some(input))
}
}
}
promiseOfChunkReadFromFile(inputs)
}, {() => inputs.foreach(_.close())})
}