【问题标题】:Creating a zip on the fly with csv files inside动态创建包含 csv 文件的 zip
【发布时间】:2013-06-03 20:50:41
【问题描述】:

我正在尝试动态创建一个 zip 文件,其中包含一堆要从 servlet 返回的 csv 文件,这非常令人困惑。一点指导会很棒。以下是我需要以某种方式协同工作的代码块:

// output stream coming from httpResponse, thats all fine
ZipOutputStream zip = new ZipOutputStream(outputStream);


// using the openCSV library to create the csv file
CSVWriter writer = new CSVWriter(Writer?); 
// what writer do I use? I want to write to memory, not a file

writer.writeNext(entries); 
writer.close();

// at this point should I have the csv file in memory somewhere? 
//and then try to copy it into the zip file?

int length;
byte[] buffer = new byte[1024 * 32];    
zip.putNextEntry(new ZipEntry(getClass() + ".csv"));

// the 'in' doesn't exist yet - where am I getting the input stream from?
while((length = in.read(buffer)) != -1)
    zip.write(buffer, 0, length);

zip.closeEntry();
zip.flush();

【问题讨论】:

  • 一个ByteArrayOutputStream?
  • 写入器接受写入器参数而不是输出流 - 我可以将它包装在 printWriter 中吗?
  • 这个答案可能对stackoverflow.com/a/68492465/3946706有帮助

标签: java csv zip


【解决方案1】:

您可以按如下方式流式传输包含 CSV 的 ZIP 文件:

try {
    OutputStream servletOutputStream = httpServletResponse.getOutputStream(); // retrieve OutputStream from HttpServletResponse
    ZipOutputStream zos = new ZipOutputStream(servletOutputStream); // create a ZipOutputStream from servletOutputStream

    List<String[]> csvFileContents  = getContentToZIP(); // get the list of csv contents. I am assuming the CSV content is generated programmatically
    int count = 0;
    for (String[] entries : csvFileContents) {
        String filename = "file-" + ++count  + ".csv";
        ZipEntry entry = new ZipEntry(filename); // create a zip entry and add it to ZipOutputStream
        zos.putNextEntry(entry);

        CSVWriter writer = new CSVWriter(new OutputStreamWriter(zos));  // There is no need for staging the CSV on filesystem or reading bytes into memory. Directly write bytes to the output stream.
        writer.writeNext(entries);  // write the contents
        writer.flush(); // flush the writer. Very important!
        zos.closeEntry(); // close the entry. Note : we are not closing the zos just yet as we need to add more files to our ZIP
    }

    zos.close(); // finally closing the ZipOutputStream to mark completion of ZIP file
} catch (Exception e) {
    log.error(e); // handle error
}

【讨论】:

  • 当然可以,但是我从不在任何地方调用 writer.close 可以吗?
  • 是的。编写器将字节直接写入 servlet 的输出流。如果您注意到您在整个代码中使用相同的流。写完后只需要关闭一次。我们稍后会在 catch 块之前的代码中这样做
  • @nadirsaghar 你能告诉我你从哪里得到`getContentToZIP();`方法吗?我在网上找不到。
  • 生成一个 30mb 的 zip 文件需要多少时间?(里面有多个 csv)
  • 如果有人遇到我遇到的同样问题:我使用的是 javacsv 库而不是 opencsv,与 opencsv 不同,javacsv 中的 CsvWriter 类在其中包含对 close() 的调用finalize() 方法,所以当 CsvWriter 被垃圾回收时,可能会导致它过早关闭 ZipOutputStream,这会导致“Stream closed”错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-05
  • 1970-01-01
  • 1970-01-01
  • 2017-02-07
  • 1970-01-01
  • 2011-08-12
  • 2015-01-21
相关资源
最近更新 更多