Java: 如何在没有中间文件的情况下使用 ZipOutputStream 压缩 byte[]

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

要求:使用java.util.zip.ZipOutputStream压缩一个字节[]以获得另一个字节[],但不使用磁盘或内存中的任何文件(如此处)。这可能吗?

我在网上找到的所有示例都是从文件(.txt) 读取并写入文件(.zip)。 ZipOutputStream 需要一个 ZipEntry 才能使用,而 ZipEntry 需要一个文件。

但是,我的用例如下:我需要使用 zip 格式一次压缩一个文件的一个块(比如 10MB),然后将所有这些压缩块附加到一个 .zip 文件中。但是,当我解压缩 .zip 文件时,它已损坏。

我按照 中的建议使用内存中的文件来避免磁盘上的文件,但也需要一个没有这些文件的解决方案。

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

场景一: 如果 test.txt 有少量数据(小于 10 个字节),如 "this",则 unzip test.txt.zip 产生 try.txt,其中包含 "this"。

场景二: 如果 test.txt 有更大的数据量(超过 10 个字节),如 "this is a test for zip output stream and it is not working" 那么 unzip test.txt.zip 会产生 try.txt 数据碎片并且不完整。

这10个字节是testZipBytes中的缓冲区大小,是zipBytes一次压缩的数据量

预期(或更确切地说是期望): 1. unzip test.txt.zip 不使用我在 MemoryFile 中提供的 "try.txt" 文件名,而是解压缩到文件名 test.txt 本身。 2. 解压缩后的数据没有损坏,并按原样生成输入数据。 3. 我对 GzipOutputStream 做了同样的事情,它工作得很好。

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 ). Is this even possible?

是的,您已经做到了。在您的示例中,您实际上并不需要 MemoryFile;只需将其从您的实施中删除,然后改写 ZipEntry entry = new ZipEntry("try.txt")

但是您无法连接 10MB 文件块的 zip 并为组合文件获取有效的 zip 文件。压缩不是那样工作的。也许你可以有一个解决方案,可以最大限度地减少内存中的内存量。但是将原始文件分成块似乎行不通。