2015-08-20 11 views
8

Ich habe eine große .csv Datei (ca. 300 MB), die von einem Remote-Host gelesen und in eine Zieldatei geparst wird, aber ich muss nicht alle Zeilen in die Zieldatei kopieren. Während des Kopierens muss ich jede Zeile aus der Quelle lesen, und wenn sie ein Prädikat übergibt, füge die Zeile zur Zieldatei hinzu.Wie kann ich eine große Datei über CSVParser verarbeiten?

Ich nehme an, dass Apache CSV (apache.commons.csv) nur ganze Datei

CSVFormat csvFileFormat = CSVFormat.EXCEL.withHeader(); 
CSVParser csvFileParser = new CSVParser("filePath", csvFileFormat); 
List<CSVRecord> csvRecords = csvFileParser.getRecords(); 
analysieren kann

so kann ich nicht BufferedReader verwenden. Basierend auf meinem Code sollte eine new CSVParser() Instanz für jede Zeile erstellt werden, was ineffizient aussieht.

Wie kann ich im obigen Fall eine einzelne Zeile (mit bekanntem Header der Tabelle) analysieren?

Antwort

10

Egal, was Sie tun, alle Daten aus Ihrer Datei werden auf Ihren lokalen Rechner übertragen, weil Ihr System es analysieren muss, um die Gültigkeit zu ermitteln. Ob die Datei über eine Datei eintrifft, die durch den Parser gelesen wird (so dass Sie jede Zeile analysieren können), oder ob Sie einfach die gesamte Datei für Parsing-Zwecke kopieren, es wird alles auf lokal übertragen. Sie müssen die Daten lokal abrufen und dann den Überschuss abschneiden.

Aufruf csvFileParser.getRecords() ist bereits eine verlorene Schlacht, weil the documentation erklärt, dass diese Methode jede Zeile Ihrer Datei in den Speicher lädt. Um den Datensatz zu analysieren und gleichzeitig aktiven Speicher zu sparen, sollten Sie stattdessen über jeden Datensatz iterieren. die Dokumentation des folgenden Code lädt einen Datensatz in dem Speicher zu einer Zeit bedeutet:

CSVParser csvFileParser = CSVParser.parse(new File("filePath"), csvFileFormat); 

for (CSVRecord csvRecord : csvFileParser) { 
    ... // qualify the csvRecord; output qualified row to new file and flush as needed. 
} 

Da Sie erklärte, dass "filePath" nicht lokal ist, ist die oben genannte Lösung fehleranfällig aufgrund von Verbindungsproblemen. Um Konnektivitätsprobleme zu vermeiden, empfehle ich Ihnen, die gesamte Remote-Datei auf lokal zu kopieren, sicherzustellen, dass die Datei korrekt kopiert wird, indem Sie Prüfsummen vergleichen, die lokale Kopie analysieren, um Ihre Zieldatei zu erstellen, und anschließend die lokale Kopie löschen.

0

Dies ist eine späte Antwort, aber Sie können einen BufferedReader mit dem CSVParser verwenden:

try (BufferedReader reader = new BufferedReader(new FileReader(fileName), 1048576 * 10)) { 
    Iterable<CSVRecord> records = CSVFormat.RFC4180.parse(reader); 
    for (CSVRecord line: records) { 
     // Process each line here 
    } 
catch (...) { // handle exceptions from your bufferedreader here