Haskell Parsec中的流式读写
Haskell Parsec中的流式读写,haskell,parsec,Haskell,Parsec,给定parsec库中的Parser,执行流式读取(从输入文件)和写入(将解析的blob/line附加到输出文件)的好方法是什么。下面是来自Text.Parsec.ByteString的示例:
main = do{ result <- parseFromFile numbers "digits.txt"
; case result of
Left err -> print err
Ri
给定parsec
库中的Parser
,执行流式读取(从输入文件)和写入(将解析的blob/line附加到输出文件)的好方法是什么。下面是来自Text.Parsec.ByteString
的示例:
main = do{ result <- parseFromFile numbers "digits.txt"
; case result of
Left err -> print err
Right xs -> print (sum xs)
}
因此,为了确定是否存在错误,似乎需要整个输入。如果我没有弄错的话,在看到所有输入之前,代码无法编写输出。是否有其他方法可以使用Parsec
进行流式输入和输出(而不是attoprasec
,如果可以避免的话-我希望能够访问Parsec
的错误报告)。我试图解析的文件很大(50+GB)。因此,我需要将解析器代码与流式输入和输出连接起来。如果有一个很好的例子,指点会很感激
更新
刚刚从AttoParsec
中发现Parsec
无法增量使用输入。因此,在Parsec
中无法进行流式处理。现在,我将对解析器进行重构,使之成为AttoParsec
通常只关注少量复杂数据。想想编程和标记语言,困难的二进制格式等等。这有两个影响:
它针对错误消息(复杂数据需要)而不是性能(少量数据不需要)进行了优化
它不进行流解析(同样,对于少量数据不需要)
采取相反的方法:它关注大量(相对)简单的数据。想想挖掘日志文件、读取测量值、从互联网收集数据流等等。这有两个影响:
它针对错误消息的性能进行了优化
它是围绕流媒体构建的
使用Attoparsec进行流式解析的原理是,您选择解析某个内容,当它消耗了您的所有输入时,它将返回一个值,该值表示它希望获得更多的输入
然而,请注意,即使使用Attoparsec解析一个大文件,它仍然可能占用大量内存。这是因为Attoparsec(与Parsec相反)在与解析器不匹配时总是回溯,因此它不能丢弃“已经解析”的数据,因为以后可能需要它
解决方法是,正如注释中所暗示的,只为数据的单个部分(类似于日志文件的一行)编写解析器,然后从Haskell代码中为日志文件的每一行重复运行该解析器。这允许解析占用恒定的空间
通常集中于较小数量的复杂数据。想想编程和标记语言,困难的二进制格式等等。这有两个影响:
它针对错误消息(复杂数据需要)而不是性能(少量数据不需要)进行了优化
它不进行流解析(同样,对于少量数据不需要)
采取相反的方法:它关注大量(相对)简单的数据。想想挖掘日志文件、读取测量值、从互联网收集数据流等等。这有两个影响:
它针对错误消息的性能进行了优化
它是围绕流媒体构建的
使用Attoparsec进行流式解析的原理是,您选择解析某个内容,当它消耗了您的所有输入时,它将返回一个值,该值表示它希望获得更多的输入
然而,请注意,即使使用Attoparsec解析一个大文件,它仍然可能占用大量内存。这是因为Attoparsec(与Parsec相反)在与解析器不匹配时总是回溯,因此它不能丢弃“已经解析”的数据,因为以后可能需要它
解决方法是,正如注释中所暗示的,只为数据的单个部分(类似于日志文件的一行)编写解析器,然后从Haskell代码中为日志文件的每一行重复运行该解析器。这允许解析占用恒定的空间
通常集中于较小数量的复杂数据。想想编程和标记语言,困难的二进制格式等等。这有两个影响:
它针对错误消息(复杂数据需要)而不是性能(少量数据不需要)进行了优化
它不进行流解析(同样,对于少量数据不需要)
采取相反的方法:它关注大量(相对)简单的数据。想想挖掘日志文件、读取测量值、从互联网收集数据流等等。这有两个影响:
它针对错误消息的性能进行了优化
它是围绕流媒体构建的
使用Attoparsec进行流式解析的原理是,您选择解析某个内容,当它消耗了您的所有输入时,它将返回一个值,该值表示它希望获得更多的输入
然而,请注意,即使使用Attoparsec解析一个大文件,它仍然可能占用大量内存。这是因为Attoparsec(与Parsec相反)在与解析器不匹配时总是回溯,因此它不能丢弃“已经解析”的数据,因为以后可能需要它
解决方法是,正如注释中所暗示的,只为数据的单个部分(类似于日志文件的一行)编写解析器,然后从Haskell代码中为日志文件的每一行重复运行该解析器。这允许解析占用恒定的空间
通常集中于较小数量的复杂数据。想想编程和标记语言,困难的二进制格式等等。这有两个影响:
它针对错误消息(复杂数据需要)而不是性能(少量数据不需要)进行了优化
没有
parseFromFile :: Parser a -> String -> IO (Either ParseError a)