给定Parser库中的parsec,什么是进行流读取(从输入文件)和写入(将解析的blob/行附加到输出文件)的好方法。下面是Text.Parsec.ByteString的一个示例
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签名,在我们看到所有输入之前,我们似乎不能懒洋洋地流并将输出输送到输出文件中。这是类型签名:
parseFromFile :: Parser a -> String -> IO (Either ParseError a)因此,为了确定是否有错误,它需要整个输入。如果我没有弄错,在看到所有输入之前,代码无法编写输出。是否有另一种方法可以使用Parsec进行流输入和输出(如果可以避免,则不是AttoParsec --我希望能够访问Parsec的错误报告)。我试图解析的文件是巨大的(50+GB)。因此,我需要用流输入和输出连接解析器代码。如果有一个很好的例子在某处,指针将被赞赏。
更新
刚从AttoParsec 文档中发现,Parsec不能增量地使用输入。因此,没有办法在Parsec中进行流处理。我现在将解析器重构为AttoParsec。
发布于 2015-04-14 10:31:40
帕秒通常关注的是较小数量的复杂数据。想想编程和标记语言,困难的二进制格式等等。这有两个影响:
阿托帕塞特采取了相反的方法:它关注大量(相对)简单的数据。想想挖掘日志文件,读取测量值,从互联网收集数据流等等。这有两个影响:
使用Attoparsec进行流解析的原则是,您选择解析某个内容,当它消耗了您的所有输入时,它将返回一个值,该值指示它希望得到更多的输入。
但是,请注意,即使使用Attoparsec来解析一个巨大的文件,它也可能占用大量的内存。这是因为Attoparsec (相对于Parsec)总是在与解析器匹配失败时回溯,因此不能丢弃“已经解析的”数据,因为以后可能需要它。 正如注释中所暗示的,解决这一问题的方法是只为数据的单个部分(类似于日志文件的一行)编写一个解析器,然后从Haskell代码中对日志文件的每一行重复运行该解析器。这允许解析占用常量空间。
发布于 2015-04-14 16:05:20
给定parseFromFile签名,在我们看到所有输入之前,我们似乎不能懒洋洋地流并将输出输送到输出文件中。..。因此,为了确定是否有错误,它需要整个输入。如果我没有弄错,在看到所有输入之前,代码无法编写输出。
这对于Attoparsec和Parsec都是一样的。虽然Attoparsec为您提供了对输入增量消耗的更多控制,但它仍然使解析器无法表示输出的增量生产。解析器必须运行到完成才能报告成功,获得解析器输出的唯一方法是通过表示解析器成功的数据构造函数。
https://stackoverflow.com/questions/29618031
复制相似问题