Java - Aufteilung einer großen SQL -Textdatei auf dem Delimeter mit Scanner (outofMemoryError)

StackOverflow https://stackoverflow.com/questions/20353915

  •  25-08-2022
  •  | 
  •  

Frage

Ich versuche eine Anwendung zu schreiben, die eine sehr große SQL -Textdatei ~ 60 GB (257 Millionen Zeilen) einnimmt und jede der Kopieranweisungen in separate Textdateien aufteilt.

Der Code, den ich derzeit verwende, verursacht jedoch ein OutofMemoryError, da die Zeilen, die die Scannerpuffergrenze überschreiten,. Die erste Aussage wird ~ 40 Millionen Zeilen lang sein.

public static void readFileByDelimeter(String fileName, String requestType, String output) throws FileNotFoundException {

//creating file instance
File file = new File(fileName);

//create scanner instance
Scanner scanner = new Scanner(file, "latin1");

//set custom delimeter
scanner.useDelimeter("COPY");

int number = 0;
System.out.println("Running......");
while (scanner.hasNext()){
    String line = scanner.next();
    if (line.length() > 20) {
        //save statements to seperate SQL files
        PrintWriter out = new PrintWriter("statement" + number + ".sql");
        out.println("COPY" + line.trim());
        out.close();
        }
        number++;
    }

System.out.println("Completed");
}

Bitte geben Sie eine Empfehlung, ob dies die falsche Methode für die Durchführung dieser oder Änderungen der vorhandenen Methode ist.

Vielen Dank

War es hilfreich?

Lösung

Erstens, warum Sie erstellen oder einen anderen Prozess erstellen, ist eine 60 -GB -Datei! Vielleicht müssen Sie sich diesen Prozess ansehen, um diesen Prozess zu beheben, um eine kleinere SQL -Textdatei zu generieren, anstatt einen neuen Prozess zu erstellen. Wenn dies jedoch eine einmalige Sache ist, die Sie tun müssen, könnte dies in Ordnung sein, aber um Ihre Frage zu beantworten, würde ich den BufferedReader verwenden, um die Datensätze zu lesen und zu verarbeiten, wenn es sich um eine große Datei handelt, wie Sie angegeben sind.

BufferedReader br = new BufferedReader(new FileReader(file));
String line;
while ((line = br.readLine()) != null) {
   // process the line. and write into your output file and close the file.
   }
br.close();

Andere Tipps

Ich persönlich: Ich benutze BufferedReader am Standpunkt des Scanners. Es hat auch eine praktische Readline () -Methode und ich hatte noch nie Probleme mit der Leistung. Das einzige, was Sie manuell prüfen müssen, ob eine Lektüre eine Linie ist, die Sie verarbeiten möchten, aber das ist normalerweise so einfach wie die Anwendung der String -Klassenmethoden.

Das ist keine Antwort auf Ihre tatsächliche Frage, aber ich halte es für eine angemessene benutzerfreundliche Alternative.

Probieren Sie so etwas (aber hübscher) aus:

Scanner sc = new Scanner(new BufferedReader(new FileReader(file)));

Dies dekoriert das Ganze mit einem BufferedReader, was bedeutet, dass nicht der gesamte Inhalt der Datei gleichzeitig in den Speicher geladen wird. Sie können den Scanner auf die gleiche Weise verwenden.

Versuchen Sie, einen BufferedReader zu verwenden. Direkte Verwendung von Scanner mit Datei- oder Rohdatei -Streams. Laden Sie die Daten im Speicher und spülen Sie sie nicht auf GC aus. Der BET -Ansatz besteht darin, BufferedReader zu verwenden und jeweils eine Zeile zu lesen und manuelle Zeichenfolgenprüfungen und Spalten durchzuführen. Wenn Sie auf diese Weise richtig gemacht werden, können Sie der GC genügend Gelegenheit geben, bei Bedarf das Gedächtnis zurückzugewinnen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top