Ich lese eine große tsv-Datei (~ 40G) und versuche, sie zu beschneiden, indem ich Zeile für Zeile lese und nur bestimmte Zeilen in eine neue Datei drucke. Allerdings bekomme ich immer die folgende Ausnahme:
%Vor%Unten ist der Hauptteil des Codes. Ich habe die Puffergröße für den Fall 8192 angegeben. Löscht Java den Puffer nicht, wenn die Puffergröße erreicht ist? Ich sehe hier nicht, was den großen Speicherverbrauch verursachen könnte. Ich habe versucht, die Heap-Größe zu erhöhen, aber es machte keinen Unterschied (Maschine mit 4 GB RAM). Ich habe auch versucht, die Ausgabedatei alle X Zeilen zu löschen, aber es half auch nicht. Ich denke, vielleicht muss ich zum GC telefonieren, aber es klingt nicht richtig.
Irgendwelche Gedanken? Danke vielmals. BTW - Ich weiß, ich sollte trim () nur einmal aufrufen, speichern und dann verwenden.
%Vor%Am wahrscheinlichsten ist, dass die Datei keine Zeilenabbrecher hat und der Leser einfach so lange wächst, bis der StringBuffer nicht mehr ausreicht.
Die Lösung wäre, eine feste Anzahl von Bytes gleichzeitig zu lesen, indem die 'read'-Methode des Lesers verwendet wird und dann nach neuen Zeilen (oder anderen syntaktischen Token) innerhalb der kleineren Puffer gesucht wird.
Sind Sie sicher, dass die Zeilen in der Datei durch Zeilenumbrüche getrennt sind?
Ich habe 3 Theorien:
Die Eingabedatei ist nicht UTF-8, sondern ein unbestimmtes Binärformat, das beim Lesen als UTF-8 zu extrem langen Zeilen führt.
Die Datei enthält einige extrem lange "Zeilen" ... oder überhaupt keine Zeilenumbrüche.
Etwas anderes passiert im Code, den Sie uns nicht zeigen; z.B. Sie fügen neue Elemente zu set
hinzu.
Um die Diagnose zu erleichtern:
od
(unter UNIX / LINUX), um zu bestätigen, dass die Eingabedatei wirklich gültige Zeilenabschlusszeichen enthält. d.h. CR, NL oder CR NL. Zur Erinnerung: Ihre etwas suboptimale Verwendung von trim
hat keine Auswirkungen auf dieses Problem.
Eine Möglichkeit besteht darin, dass Ihnen während einer Garbage Collection der Heap-Speicherplatz knapp wird. Die Hotspot-JVM verwendet standardmäßig einen parallelen Kollektor, was bedeutet, dass Ihre Anwendung möglicherweise Objekte schneller zuordnen kann als der Kollektor sie zurückfordern kann. Ich konnte einen OutOfMemoryError mit angeblich nur 10K lebenden (kleinen) Objekten verursachen, indem ich schnell zuordnende und verwerfende.
Sie können stattdessen versuchen, den alten (vor 1.5) seriellen Kollektor mit der Option -XX:+UseSerialGC
zu verwenden. Es gibt mehrere andere "erweiterte" Optionen, die Sie zum Abstimmen verwenden können Sammlung.