首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Parsec中的流读写

Parsec中的流读写
EN

Stack Overflow用户
提问于 2015-04-14 02:06:37
回答 2查看 700关注 0票数 0

给定Parser库中的parsec,什么是进行流读取(从输入文件)和写入(将解析的blob/行附加到输出文件)的好方法。下面是Text.Parsec.ByteString的一个示例

代码语言:javascript
复制
main    = do{ result <- parseFromFile numbers "digits.txt"
             ; case result of
                 Left err  -> print err
                 Right xs  -> print (sum xs)
             }

上面的示例只从"digits.txt“读取,并且在看到所有输入之前不会有输出。让我们假设,我们不需要收集所有的值并执行上述的缩减(sum),我们希望以流的方式将所有的xs输出写到"digitsOut.txt“(从digits.txt读取行并将其写入digitsOut.txt)。给定parseFromFile签名,在我们看到所有输入之前,我们似乎不能懒洋洋地流并将输出输送到输出文件中。这是类型签名:

代码语言:javascript
复制
parseFromFile :: Parser a -> String -> IO (Either ParseError a)

因此,为了确定是否有错误,它需要整个输入。如果我没有弄错,在看到所有输入之前,代码无法编写输出。是否有另一种方法可以使用Parsec进行流输入和输出(如果可以避免,则不是AttoParsec --我希望能够访问Parsec的错误报告)。我试图解析的文件是巨大的(50+GB)。因此,我需要用流输入和输出连接解析器代码。如果有一个很好的例子在某处,指针将被赞赏。

更新

刚从AttoParsec 文档中发现,Parsec不能增量地使用输入。因此,没有办法在Parsec中进行流处理。我现在将解析器重构为AttoParsec

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-14 10:31:40

帕秒通常关注的是较小数量的复杂数据。想想编程和标记语言,困难的二进制格式等等。这有两个影响:

  1. 它被优化为错误消息(需要复杂的数据)而不是性能(不需要少量的数据)。
  2. 它不执行流解析(同样,不需要少量的数据)

阿托帕塞特采取了相反的方法:它关注大量(相对)简单的数据。想想挖掘日志文件,读取测量值,从互联网收集数据流等等。这有两个影响:

  1. 它被优化为性能优于错误消息。
  2. 它是围绕着流建立的。

使用Attoparsec进行流解析的原则是,您选择解析某个内容,当它消耗了您的所有输入时,它将返回一个值,该值指示它希望得到更多的输入。

但是,请注意,即使使用Attoparsec来解析一个巨大的文件,它也可能占用大量的内存。这是因为Attoparsec (相对于Parsec)总是在与解析器匹配失败时回溯,因此不能丢弃“已经解析的”数据,因为以后可能需要它。 正如注释中所暗示的,解决这一问题的方法是只为数据的单个部分(类似于日志文件的一行)编写一个解析器,然后从Haskell代码中对日志文件的每一行重复运行该解析器。这允许解析占用常量空间。

票数 3
EN

Stack Overflow用户

发布于 2015-04-14 16:05:20

给定parseFromFile签名,在我们看到所有输入之前,我们似乎不能懒洋洋地流并将输出输送到输出文件中。..。因此,为了确定是否有错误,它需要整个输入。如果我没有弄错,在看到所有输入之前,代码无法编写输出。

这对于Attoparsec和Parsec都是一样的。虽然Attoparsec为您提供了对输入增量消耗的更多控制,但它仍然使解析器无法表示输出的增量生产。解析器必须运行到完成才能报告成功,获得解析器输出的唯一方法是通过表示解析器成功的数据构造函数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29618031

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档