Java: how to compress a byte[] using ZipOutputStream without intermediate file

两盒软妹~` 提交于 2019-12-11 15:39:57

问题


Requirement: compress a byte[] to get another byte[] using java.util.zip.ZipOutputStream BUT without using any files on disk or in-memory(like here https://stackoverflow.com/a/18406927/9132186). Is this even possible?

All the examples I found online read from a file(.txt) and write to a file(.zip). ZipOutputStream needs a ZipEntry to work with and that ZipEntry needs a file.

However, my use case is as follows: I need to compress a chunk (say 10MB) of a file at a time using a zip format and append all these compressed chunks to make a .zip file. But, when I unzip the .zip file then it is corrupted.

I am using in-memory files as suggested in https://stackoverflow.com/a/18406927/9132186 to avoid files on disk but need a solution without these files also.

  public void testZipBytes() {
    String infile = "test.txt";
    FileInputStream in = new FileInputStream(infile);

    String outfile = "test.txt.zip";
    FileOutputStream out = new FileOutputStream(outfile);

    byte[] buf = new byte[10];
    int len;
    while ((len = in.read(buf)) > 0) {
      out.write(zipBytes(buf));
    }
    in.close();
    out.close();
  }

  // ACTUAL function that compresses byte[]

  public static class MemoryFile {
    public String fileName;
    public byte[] contents;
  }

  public byte[] zipBytesMemoryFileWORKS(byte[] input) {
    MemoryFile memoryFile = new MemoryFile();
    memoryFile.fileName = "try.txt";
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ZipOutputStream zos = new ZipOutputStream(baos);
    ZipEntry entry = new ZipEntry(memoryFile.fileName);
    entry.setSize(input.length); 
    zos.putNextEntry(entry); 
    zos.write(input);
    zos.finish();
    zos.closeEntry();
    zos.close();
    return baos.toByteArray();
  }

Scenario 1: if test.txt has small amount of data (less than 10 bytes) like "this" then unzip test.txt.zip yeilds try.txt with "this" in it.

Scenario 2: if test.txt has larger amount of data (more than 10 bytes) like "this is a test for zip output stream and it is not working" then unzip test.txt.zip yields try.txt with broken pieces of data and is incomplete.

this 10 bytes is the buffer size in testZipBytes and is the amount of data that is compressed at a time by zipBytes

Expected (or rather desired): 1. unzip test.txt.zip does not use the "try.txt" filename i gave in the MemoryFile but rather unzips to filename test.txt itself. 2. unzipped data is not broken and yields the input data as is. 3. I have done the same with GzipOutputStream and it works perfectly fine.


回答1:


Requirement: compress a byte[] to get another byte[] using java.util.zip.ZipOutputStream BUT without using any files on disk or in-memory(like here https://stackoverflow.com/a/18406927/9132186). Is this even possible?

Yes, you've already done it. You don't actually need MemoryFile in your example; just delete it from your implementation and write ZipEntry entry = new ZipEntry("try.txt") instead.

But you can't concatenate the zips of 10MB chunks of file and get a valid zip file for the combined file. Zipping doesn't work like that. You could have a solution which minimizes how much is in memory at once, perhaps. But breaking the original file up into chunks seems unworkable.



来源:https://stackoverflow.com/questions/58243754/java-how-to-compress-a-byte-using-zipoutputstream-without-intermediate-file

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!