2014-07-03 19 views
9

Ich habe wahrscheinlich nur einen Tag der Rechenzeit vergeblich verbringen :)Gibt es eine Möglichkeit, "träge" zu lesen?

Das Problem ist, dass ich (naiv) schrieb über 3,5 GB von (komprimiert) [(Text, HashMap Text Int)] Daten in eine Datei und an diesem Punkt meines Programm abgestürzt ist. Natürlich gibt es kein finales ] am Ende der Daten und die schiere Größe macht es unmöglich, es von Hand zu bearbeiten.

Die Daten wurden über Prelude.show formatiert und genau an diesem Punkt merke ich, dass Prelude.read den gesamten Datensatz in den Speicher (unmöglich) bevor alle Daten zurückgegeben werden müssen.

Jetzt ... gibt es eine Möglichkeit, die Daten wiederherzustellen, ohne einen Parser manuell schreiben zu müssen?

aktualisieren 1

main = do 
    s <- getContents 
    let hs = read s :: [(String, M.Map String Integer)] 
    print $ head hs 

Das habe ich versucht ... aber es hält nur einem höheren Speicherbedarf, bis sie vom OS getötet wird.

+0

@ n.m. selbst dann würde "lesen" versuchen, alles in den Speicher zu schreiben, bevor ein einzelnes Element der Liste zurückgegeben wird. – fho

+0

Sorry ich missverstanden, Sie meinen Haskell 'lesen' Funktion, nicht aus der Datei lesen. –

Antwort

7

Daniels Antwort kann erweitert werden, um die gesamte Liste gleichzeitig mit dieser Funktion zu analysieren. Dann können Sie direkt auf eine Liste zugreifen, wie Sie möchten

lazyread :: Read a => [Char] -> [a] 
lazyread xs = go (tail xs) 
    where go xs = a : go (tail b) 
     where (a,b) = head $ reads xs 
+0

Großartig! Du hast gerade meinen Tag gerettet :) – fho

1

Löschen Sie manuell die Öffnung '['. Danach können Sie möglicherweise reads verwenden (beachten Sie die s), um schrittweise auf getContents zuzugreifen.

9

Sortieren von. Sie werden immer noch einen Parser manuell schreiben ... aber es ist ein sehr kurzer und sehr einfach zu schreibender Parser, weil fast alles davon an read versendet wird. Die Idee ist dies: read ist streng, aber reads, wenn an einem einzigen Element arbeiten, ist lazaisch. Wir müssen also nur die Bits entfernen, die reads nicht erwarten, wenn Sie an einem einzelnen Element arbeiten. Hier ist ein Beispiel für den Einstieg:

> let s = "[3,4,5," ++ undefined 
> reads (drop 1 s) :: [(Int, String)] 
[(3,",4,5,*** Exception: Prelude.undefined 

ich die undefined am Ende als Beweis enthalten, dass es in der Tat nicht die gesamten String lesen, bevor die analysierte 3 an der Spitze der Liste zu erzeugen.

Verwandte Themen