2013-11-04 14 views
5

Tôi đã có ứng dụng Spring MVC với khả năng tải tệp lên. Các tệp được truyền tới bộ điều khiển dưới dạng MultipartFile, từ đó dễ dàng nhận được một InputStream. Tôi đang tải lên các tệp zip chứa CSV và tôi đang cố gắng tìm cách mở CSV và đọc từng dòng một. Có rất nhiều ví dụ trên 'net đọc vào một bộ đệm kích thước cố định. Tôi đã thử điều này, nhưng các bộ đệm không tiếp nhau rất tốt và nó sớm được ra khỏi đồng bộ và sử dụng rất nhiều bộ nhớ:Đọc CSV từ một tệp zip tại một thời điểm

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

Có phải là một cách tốt hơn mà thực sự hoạt động.

+1

Jackson CsvMapper sẽ phân tích một dòng đầu vào tại một thời điểm thành một đối tượng []. Có thể là một giá trị. Nó sẽ nhanh hơn chia (",") và xử lý thoát quá. – tom

Trả lời

6

Không rõ ràng nếu điều này phù hợp với nhu cầu của bạn, nhưng bạn đã thử opencsv (http://opencsv.sourceforge.net)? Ví dụ họ thực sự trực quan:

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

Đối với trường hợp của bạn, tất cả các bạn sẽ cần là để bọc các dòng tập tin nén vào một đầu đọc đệm và vượt qua người đọc để tạo ra một CSVReader và sử dụng nó:

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

Bạn có thể sử dụng BufferedReader bao gồm phương thức readLine() thuận tiện và không tải toàn bộ nội dung của tệp vào bộ nhớ, ví dụ:

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

Điều đó sẽ không hoạt động vì tôi không thể lấy InputStream cho ZipEntry. –

+1

Biến 'input' của bạn có phải là' ZipInputStream' không? Nếu có, mã trên phải được sử dụng như 'ZipInputStream' là' InputStream' cho 'ZipEntry' hiện tại. – samlewis

Các vấn đề liên quan