2013-11-04 22 views
5

Ich habe eine Spring MVC-App mit Datei-Upload-Funktion. Dateien werden als MultipartFile an den Controller übergeben, von dem es leicht ist, einen InputStream zu erhalten. Ich lade zip-Dateien hoch, die CSVs enthalten, und ich habe Schwierigkeiten, eine Möglichkeit zu finden, die CSVs zu öffnen und sie Zeile für Zeile zu lesen. Es gibt viele Beispiele über das "Lesen in einen Puffer fester Größe". Ich habe dies versucht, aber die Puffer verketten nicht sehr gut und es wird bald nicht mehr synchron und verwendet viel Speicher:Lesen von CSVs aus einer Zip-Datei Zeile für Zeile

 ZipEntry entry = input.getNextEntry(); 

     while(entry != null) 
     { 
      if (entry.getName().matches("Data/CSV/[a-z]{0,1}[a-z]{0,1}.csv")) 
      { 
       final String fullPath = entry.getName(); 
       final String filename = fullPath.substring(fullPath.lastIndexOf('/') + 1); 

       visitor.startFile(filename);      

       final StringBuilder fileContent = new StringBuilder(); 

       final byte[] buffer = new byte[1024];     

       while (input.read(buffer) > 0) 
        fileContent.append(new String(buffer)); 

       final String[] lines = fileContent.toString().split("\n"); 

       for(String line : lines) 
       { 
        final String[] columns = line.split(","); 
        final String postcode = columns[0].replace(" ", "").replace("\"", ""); 

        if (columns.length > 3) 
         visitor.location(postcode, "", ""); 
       } 

       visitor.endFile();     
      } 

      entry = input.getNextEntry(); 
     } 

Es muss einen besseren Weg geben, die tatsächlich funktioniert.

+1

Der Jackson CsvMapper analysiert einen Eingabestream Zeile für Zeile in ein Objekt []. Könnte einen Blick wert sein. Es wird schneller als Split (",") und umgehen Sie auch entkommen. – tom

Antwort

6

Nicht klar, ob dies Ihren Anforderungen entspricht, aber haben Sie versucht, opencsv (http://opencsv.sourceforge.net)? Ihr Beispiel ist wirklich intuitiv:

CSVReader reader = new CSVReader(new FileReader("yourfile.csv")); 
String [] nextLine; 
while ((nextLine = reader.readNext()) != null) { 
    // nextLine[] is an array of values from the line 
    System.out.println(nextLine[0] + nextLine[1] + "etc..."); 
} 

Für Ihren Fall alles, was Sie brauchen, ist die gezippte Datei-Stream in einer gepufferten Leser zu wickeln und den Leser weitergeben, um eine CSVReader zu erstellen und verwenden es:

FileInputStream fis = new FileInputStream(file); 
GZIPInputStream gis = new GZIPInputStream(fis); 
InputStreamReader isr = new InputStreamReader(gis); 
BufferedReader br = new BufferedReader(isr); 
CSVReader reader = new CSVReader(br); 
1

Sie könnten eine BufferedReader verwenden, die die bequeme Methode readLine() enthält und nicht den gesamten Inhalt der Datei in den Arbeitsspeicher laden, z.

+0

Das wird nicht funktionieren, da ich keinen InputStream für den ZipEntry bekommen kann. –

+1

Ist Ihre 'Eingabe' Variable ein' ZipInputStream'? Wenn dies der Fall ist, sollte der obige Code in Ordnung sein, da "ZipInputStream" der "InputStream" für den aktuellen "ZipEntry" ist. – samlewis

Verwandte Themen