4

我在 scala 中使用本机解析器组合器库,我想用它来解析许多大文件。我设置了组合器,但是我尝试解析的文件太大而无法一次全部读入内存。我希望能够通过我的解析器从输入文件流式传输并将其读回磁盘,这样我就不需要一次将它全部存储在内存中。我当前的系统看起来像这样:

val f = Source.fromFile("myfile")
parser.parse(parser.document.+, f.reader).get.map{_.writeToFile}
f.close

这会在解析时读取整个文件,我想避免这种情况。

4

4 回答 4

7

使用 scala 的解析器组合器没有简单或内置的方法来完成此操作,它提供了实现解析表达式语法的工具。

(longest match)等运算符|||在很大程度上与流解析模型不兼容,因为它们需要广泛的回溯能力。为了完成你想做的事情,你需要重新制定你的语法,这样就永远不需要回溯。这通常比听起来要困难得多。

正如其他人所提到的,您最好的选择是研究一个初步阶段,您可以在其中分块输入(例如按行),以便您可以一次处理一部分流。

于 2013-09-26T05:29:00.127 回答
0

一种简单的方法是IteratorSource对象中抓取一个,然后像这样穿过线条:

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

于 2013-09-25T20:39:32.030 回答
0

您可以尝试作为解析包一部分 的StreamReader类。

你会像这样使用它:

val f = StreamReader( fromFile("myfile","UTF-8").reader() )

parseAll( parser, f )
于 2013-09-25T21:33:38.070 回答
0

上面提到的一张海报的最长匹配加上正则表达式的使用 source.subSequence(0, source.length) 意味着即使 StreamReader 也无济于事。

我得到的最好的笨拙答案是使用其他人提到的 getLines ,并使用块作为接受的答案提到的。我的特定输入要求我一次分块 2 行。您可以从您构建的块中构建一个迭代器,以使其不那么难看。

于 2014-02-19T20:06:21.547 回答