2013-09-25 83 views
2

我在scala中使用本地解析器組合器庫,我想用它來解析一些大文件。我有我的combinators設置,但我試圖解析的文件太大,一次不能讀入內存。我希望能夠通過解析器從輸入文件進行流式處理,並將其讀回到磁盤,以便我不需要立即將其全部存儲在內存中。我的當前系統看起來像這樣:斯卡拉解析器組合器:解析流

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

這將讀取整個文件,因爲它解析,我想避免。

回答

5

有沒有簡單的或內置的方式來完成這項使用Scala的解析器組合,這爲實現parsing expression grammars設施。

諸如|||(最長匹配)等運算符在很大程度上與流解析模型不兼容,因爲它們需要大量的回溯功能。爲了完成你想要做的事情,你需要重新制定你的語法,以便不需要回溯,有史以來。這通常比聽起來要困難得多。

正如其他人所提到的,您最好的選擇就是查看初步階段(例如按行),以便您可以一次處理一部分流。

+0

這很有道理。有什麼辦法可以利用我的頂級組合器只是一個重複的事實嗎?也就是說,我可以按照單個「文檔」大小的塊讀入流中嗎? –

+0

只要你能想出辦法(手動)分割文件,是的。然後你將每個文件分別轉交給你的語法。大多數PEG運營商(包括重複)實際上都依賴於回溯,因爲PEG的表現力是基於能夠說「試試這個,如果不行的話我們會嘗試其他的」。 –

0

這樣做是從Source對象搶Iterator然後通過線路像這樣走的一個簡單的方法:

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

0

您可以試着StreamReader類是分析軟件包的一部分。

你會使用它是這樣的:

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

parseAll(parser, f) 
0

上面提到的最長匹配結合正則表達式的使用source.subSequence(0,source.length)意味着即使StreamReader也沒有幫助。

我最好的答案是使用getLines,正如其他人提到的那樣,大塊作爲接受的答案提到。我的特殊輸入要求我一次分兩行。你可以從你構建的塊中構建一個迭代器,使其稍微不那麼難看。