Così il Play2.0 Enumeratee page mostra un esempio di utilizzo di un metodo &>
o through
modificare una Enumerator[String]
in un Enumerator[Int]
:Come scrivere un enumeratee al pezzo un enumeratore lungo diversi confini
val toInt: Enumeratee[String,Int] = Enumeratee.map[String]{ s => s.toInt }
val ints: Enumerator[Int] = strings &> toInt
C'è anche un enumeratee Enumeratee.grouped
per creare un enumeratore di blocchi da singoli elementi. Sembrava funzionare bene.
Ma quello che vedo è che il solito input sarebbe sotto forma di Array[Byte]
(che viene restituito da Enumerator.fromFile
e Enumerator.fromStream
). Con questo in mente vorrei prendere quegli input Array[Byte]
e trasformarli in un Enumerator[String]
, ad esempio dove ogni stringa è una linea (terminata da un '\n'
). I contorni delle linee e gli elementi Array[Byte]
di solito non corrispondono. Come posso scrivere un enumeratore in grado di convertire gli array chunked in stringhe chunked?
Lo scopo è quello di ridimensionare le linee al browser ogni volta che Array[Byte]
diventa disponibile e mantenere i byte rimanenti che non facevano parte di una linea completa fino a quando non arriva il prossimo blocco di input.
Idealmente mi piacerebbe avere un metodo che dato un iter: Iteratee[Array[Byte], T]
e un Enumerator[Array[Byte]]
mi darà indietro un Enumerator[T]
, dove i miei elementi T sono state analizzate da iter
.
Ulteriori informazioni: ho avuto un po 'di tempo per pulire il mio codice ed ecco un esempio specifico di ciò che sto cercando di fare. Ho le seguenti iteratees che rilevano la riga successiva:
import play.api.libs.iteratee._
type AB = Array[Byte]
def takeWhile(pred: Byte => Boolean): Iteratee[AB, AB] = {
def step(e: Input[AB], acc: AB): Iteratee[AB, AB] = e match {
case Input.EOF => Done(acc, Input.EOF)
case Input.Empty => Cont(step(_, acc))
case Input.El(arr) =>
val (taking, rest) = arr.span(pred)
if (rest.length > 0) Done(acC++ taking, Input.El(rest))
else Cont(step(_, acC++ taking))
}
Cont(step(_, Array()))
}
val line = for {
bytes <- takeWhile(b => !(b == '\n' || b == '\r'))
_ <- takeWhile(b => b == '\n' || b == '\r')
} yield bytes
E quello che mi piacerebbe fare è qualcosa di simile:
Ok.stream(Enumerator.fromFile(filename) &> chunkBy(line)).as("text/plain")
Cool. Sembrava che "grouped" avrebbe dovuto fare quello che volevo. – huynhjl