使用新线条在Scala Play20中使用BodyParser解析文件
发布时间:2020-12-16 18:56:21 所属栏目:安全 来源:网络整理
导读:请原谅这个问题的缺点,但我有一个Web应用程序,我想将一个可能很大的文件发送到服务器并让它解析格式.我正在使用Play20框架,而且我是 Scala的新手. 例如,如果我有一个csv,我想用“,”分隔每一行,最后用每个字段创建一个List [List [String]]. 目前,我认为最好
请原谅这个问题的缺点,但我有一个Web应用程序,我想将一个可能很大的文件发送到服务器并让它解析格式.我正在使用Play20框架,而且我是
Scala的新手.
例如,如果我有一个csv,我想用“,”分隔每一行,最后用每个字段创建一个List [List [String]]. 目前,我认为最好的方法是使用BodyParser(但我可能是错的).我的代码看起来像: Iteratee.fold[String,List[List[String]]]() { (result,chunk) => result = chunk.splitByNewLine.splitByDelimiter // Psuedocode } 我的第一个问题是,我如何处理下面的一个情况,其中一个块被分割在一行中间: Chunk 1: 1,2,3,4n 5,6 Chunk 2: 7,8n 9,10,11,12n 我的第二个问题是,编写我自己的BodyParser是正确的方法吗?有没有更好的方法来解析这个文件?我主要担心的是我想允许文件非常大,所以我可以在某个时刻刷新缓冲区而不是将整个文件保存在内存中. 解决方法
如果你的csv不包含转义的换行符,那么在不将整个文件放入内存的情况下进行渐进式解析非常容易. iteratee库在
play.api.libs.iteratee.Parsing 中附带了一个方法搜索:
def search (needle: Array[Byte]): Enumeratee[Array[Byte],MatchInfo[Array[Byte]]] 它会将您的流划分为Matched [Array [Byte]]和Unmatched [Array [Byte]] 然后,您可以组合第一个带有标题的iteratee和另一个将折叠成umatched结果的iteratee.这应该类似于以下代码: // break at each match and concat unmatches and drop the last received element (the match) val concatLine: Iteratee[Parsing.MatchInfo[Array[Byte]],String] = ( Enumeratee.breakE[Parsing.MatchInfo[Array[Byte]]](_.isMatch) ><> Enumeratee.collect{ case Parsing.Unmatched(bytes) => new String(bytes)} &>> Iteratee.consume() ).flatMap(r => Iteratee.head.map(_ => r)) // group chunks using the above iteratee and do simple csv parsing val csvParser: Iteratee[Array[Byte],List[List[String]]] = Parsing.search("n".getBytes) ><> Enumeratee.grouped( concatLine ) ><> Enumeratee.map(_.split(',').toList) &>> Iteratee.head.flatMap( header => Iteratee.getChunks.map(header.toList ++ _) ) // an example of a chunked simple csv file val chunkedCsv: Enumerator[Array[Byte]] = Enumerator("""a,b,c ""","1,3",""" 4,5,6 7,8,""","""9 """) &> Enumeratee.map(_.getBytes) // get the result val csvPromise: Promise[List[List[String]]] = chunkedCsv |>>> csvParser // eventually returns List(List(a,c),List(1,3),List(4,6),List(7,9)) 当然,您可以改进解析.如果您这样做,我将不胜感激,如果您与社区分享. 所以你的Play2控制器将是这样的: val requestCsvBodyParser = BodyParser(rh => csvParser.map(Right(_))) // progressively parse the big uploaded csv like file def postCsv = Action(requestCsvBodyParser){ rq: Request[List[List[String]]] => //do something with data } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- angularjs – “meteor mongo”崩溃,出现“错误:EINVAL,无
- twitter-bootstrap – Twitter Bootstrap 3:右对齐的折叠导
- 如何使用AngularJS或Javascript提供下载的文件?
- angular – 错误:由SyntaxError.ZoneAwareError模块’AppM
- 下一代计费解决方案的五大要素
- 角度 – Ionic2 / 3 – 标题按钮图标具有不同的大小然后自动
- Scala工厂使用apply方法的泛型类型?
- 更改vimrc的默认位置
- 用dragsort +bootstrap+php实现 table拖动自动保持排序,前
- 你在哪里拆分长Scala功能签名?