Как написать enumeratee для разбивки перечислителя по разным границам

Итак, страница Play2.0 Enumeratee показывает пример использования &>или throughдля преобразования Enumerator[String]в Enumerator[Int]:

val toInt: Enumeratee[String,Int] = Enumeratee.map[String]{ s => s.toInt }
val ints: Enumerator[Int] = strings &> toInt

. Существует также метод Enumeratee.groupedдля создания перечислителя фрагментов из отдельных элементов. Это, казалось, работало нормально.

Но я вижу, что обычный ввод будет в форме Array[Byte](, который возвращается Enumerator.fromFileиEnumerator.fromStream). Имея это в виду, я хотел бы взять эти входные данные Array[Byte]и превратить их в Enumerator[String], например, где каждая строка представляет собой строку (, заканчивающуюся'\n'). Границы линий и элементов Array[Byte]обычно не совпадают. Как написать перечислитель, который может преобразовывать массивы с фрагментами в строки с фрагментами?

Цель состоит в том, чтобы передать эти строки обратно в браузер по мере того, как Array[Byte]становится доступным, и сохранить оставшиеся байты, которые не были частью полной строки, до тех пор, пока не появится следующий входной фрагмент.

В идеале я хотел бы иметь метод, который с учетом iter: Iteratee[Array[Byte], T]и Enumerator[Array[Byte]]возвращает мне Enumerator[T], где мои T элементы были проанализированы iter.

Дополнительная информация :У меня было немного времени, чтобы почистить мой код, и вот конкретный пример того, что я пытаюсь сделать. У меня есть следующие итерации, которые обнаруживают следующую строку:

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

И я хотел бы сделать что-то вроде этого:

Ok.stream(Enumerator.fromFile(filename) &> chunkBy(line)).as("text/plain")

7
задан huynhjl 28 April 2012 в 07:38
поделиться