我在scala中使用本机解析器组合器库,我想用它来解析许多大文件。我已经设置了组合器,但是我要解析的文件太大而无法一次性读入内存。我希望能够通过我的解析器从输入文件流式传输并将其读回磁盘,这样我就不需要将它全部存储在内存中。我当前的系统看起来像这样:
val f = Source.fromFile("myfile")
parser.parse(parser.document.+, f.reader).get.map{_.writeToFile}
f.close
这会在解析时读取整个文件,我想避免使用它。
答案 0 :(得分:5)
使用scala的解析器组合器没有简单或内置的方法来实现这一点,它提供了实现parsing expression grammars的工具。
|||
(最长匹配)等运算符与流解析模型在很大程度上不兼容,因为它们需要广泛的回溯功能。为了完成你想要做的事情,你需要重新制定你的语法,这样就不需要回溯,永远。这通常比听起来要难得多。
正如其他人所提到的,你最好的选择是调查一个初步阶段,在这个阶段你输入(例如按行),这样你就可以一次处理一部分流。
答案 1 :(得分:0)
一种简单的方法是从Iterator
对象中抓取Source
,然后像这样走过这些行:
val source = Source.fromFile("myFile")
val lines = source.getLines
for (line <- lines) {
// Do magic with the line-value
}
source.close // Close the file
但是你需要能够在你的解析器中逐一使用这些行。
来源:https://groups.google.com/forum/#!topic/scala-user/LPzpXo3sUVE
答案 2 :(得分:0)
您可以尝试作为解析包一部分的StreamReader类。
你可以使用它:
val f = StreamReader( fromFile("myfile","UTF-8").reader() )
parseAll( parser, f )
答案 3 :(得分:0)
作为上面提到的一张海报的最长匹配与使用source.subSequence(0,source.length)的正则表达式相结合意味着甚至StreamReader也无济于事。
我所拥有的最好的kludgy答案是使用getLines,正如其他人所提到的那样,并且chunk作为接受的答案提到。我的特殊输入要求我一次分块2行。你可以从你构建的块中构建一个迭代器,使其稍微不那么难看。