Scala:读取枚举器[T]的一些数据并返回剩余的枚举器[T]
我正在使用playframework的异步I / O库,它使用Iteratees和Enumerators.我现在有一个Iterator [T]作为数据接收器(简化说它是一个Iterator [Byte],它将其内容存储到一个文件中).此迭代器[Byte]被传递给处理写入的函数.
但在编写之前我想在文件开头添加一些统计信息(为简化说它是一个字节),所以我在将迭代器传递给write函数之前按以下方式传递: def write(value: Byte,output: Iteratee[Byte]): Iteratee[Byte] = Iteratee.flatten(output.feed(Input.El(value))) 当我现在从磁盘读取存储的文件时,我得到了一个Enumerator [Byte]. def read(input: Enumerator[Byte]): (Byte,Enumerator[Byte]) = { val firstEnumeratorEntry = ... val remainingEnumerator = ... (firstEnumeratorEntry,remainingEnumerator) } 但我不知道如何做到这一点.如何从枚举器中读取一些字节并获取剩余的枚举器? 使用InputStream替换带有OutputStream和Enumerator [Byte]的Iteratee [Byte],这将非常简单: def write(value: Byte,output: OutputStream) = { output.write(value) output } def read(input: InputStream) = (input.read,input) 但是我需要play框架的异步I / O. 解决方法
这是通过在Iteratee和一个适当的(种类)状态累加器(这里的元组)中折叠来实现此目的的一种方法
我去读路由文件,第一个字节将作为Char读取,另一个将作为UTF-8字节串附加到字符串. def index = Action { /*let's do everything asyncly*/ Async { /*for comprehension for read-friendly*/ for ( i <- read; /*read the file */ (r:(Option[Char],String)) <- i.run /*"create" the related Promise and run it*/ ) yield Ok("first : " + r._1.get + "n" + "rest" + r._2) /* map the Promised result in a correct Request's Result*/ } } def read = { //get the routes file in an Enumerator val file: Enumerator[Array[Byte]] = Enumerator.fromFile(Play.getFile("/conf/routes")) //apply the enumerator with an Iteratee that folds the data as wished file(Iteratee.fold((None,""):(Option[Char],String)) { (acc,b) => acc._1 match { /*on the first chunk*/ case None => (Some(b(0).toChar),acc._2 + new String(b.tail,Charset.forName("utf-8"))) /*on other chunks*/ case x => (x,acc._2 + new String(b,Charset.forName("utf-8"))) } }) } 编辑 我发现了使用Enumeratee的另一种方法,但它需要创建2个枚举器(一个短暂的).但它更优雅一点.我们使用“种类”Enumeratee,但Traversal使用比Enumeratee(chunck级别)更精细的级别. 此外,现在read2的签名比你想要的更接近,因为它返回2个枚举器(距离Promise,Enumerator不远) def index = Action { Async { val (first,rest) = read2 val enee = Enumeratee.map[Array[Byte]] {bs => new String(bs,Charset.forName("utf-8"))} def useEnee(enumor:Enumerator[Array[Byte]]) = Iteratee.flatten(enumor &> enee |>> Iteratee.consume[String]()).run.asInstanceOf[Promise[String]] for { f <- useEnee(first); r <- useEnee(rest) } yield Ok("first : " + f + "n" + "rest" + r) } } def read2 = { def create = Enumerator.fromFile(Play.getFile("/conf/routes")) val file: Enumerator[Array[Byte]] = create val file2: Enumerator[Array[Byte]] = create (file &> Traversable.take[Array[Byte]](1),file2 &> Traversable.drop[Array[Byte]](1)) } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |