2013-11-04 14 views
5

Mam aplikację Spring MVC z możliwością przesyłania plików. Pliki są przesyłane do kontrolera jako MultipartFile, z którego łatwo jest uzyskać InputStream. Przesyłam pliki zip, które zawierają pliki CSV i staram się znaleźć sposób na otwieranie plików CSV i odczytywanie ich po linii. Istnieje wiele przykładów na "sieć odczytu do bufora o ustalonych rozmiarach. Próbowałem, ale bufory nie złączyć się bardzo dobrze i szybko wychodzi z synchronizacją i zużywa dużo pamięci:Odczytywanie plików CSV z pliku zip po linii w czasie

 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(); 
     } 

musi istnieć lepszy sposób, że faktycznie działa.

+1

Aplikacja Jackson CsvMapper będzie analizować strumień wejściowy po linii na obiekt []. Może warto rzucić na to okiem. Będzie szybszy niż split (",") i będzie również obsługiwał ucieczkę. – tom

Odpowiedz

6

Nie jest jasne, czy to pasuje do twoich potrzeb, ale czy próbowałeś opencsv (http://opencsv.sourceforge.net)? Ich przykładem jest naprawdę intuicyjna:

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..."); 
} 

Twoim przypadku, wszystko, co potrzebne jest, aby owinąć spakowanego pliku Stream do buforowanego czytelnika i przekazać czytelnikowi stworzyć CsvReader i używać go:

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

Można użyć opcji BufferedReader, która zawiera wygodną metodę readLine() i nie będzie ładować całej zawartości pliku do pamięci, np.

BufferedReader in = new BufferedReader(new InputStreamReader(input), 1024); 
String line=null; 
while((line=br.readLine())!=null) { 
    String[] columns = line.split(","); 
    //rest of your code 
} 
+0

To nie zadziała, ponieważ nie mogę uzyskać InputStream dla ZipEntry. –

+1

Czy twoja zmienna wejściowa to 'ZipInputStream'? Jeśli tak, powyższy kod powinien być w porządku, ponieważ 'ZipInputStream' jest' InputStream' dla bieżącego 'ZipEntry'. – samlewis