连接两个压缩字节数组

concatenate two zipped byte arrays

你好,我有一个 map reduce 作业,它根据某种分组算法将不同的字节数组合并在一起。

我尝试使用 Java Deflater 单独压缩每个数组,但是当我尝试提取生成的压缩字节数组时,它只是我提取的第一个子数组。

是否可以将字节数组压缩后直接连接然后提取,或者情况并非如此?

我想要的是:

byte array1[] - zip
byte array2[] - zip
byte array3[] = append(array1,array2).
unzip resulting array3.

当我解压缩它时,我只收到数组 1。

zip 文件是结构化的,它们不仅包含 "zipped" 数据。对于文件中的每个条目,都有一个本地 header 和相应的条目数据。在文件末尾有一个 中央目录 ,它列举了存档中包含的所有 zip 条目以及这些条目开始的偏移量。你可能会想到一个大致像这样的 zip 文件:

[entry-header,data][entry-header,data].....[central dir with entry meta-data][end-of-file]

您不能只 "merge" 两个 zip 文件作为字节数组,因为结果将不是有效的 zip。

这可以通过简单的循环更有效地完成,但如果有人决定使用 java 8 的 Stream,他们可能会尝试这样的事情。我还没有测试过,但假设有一个函数可以将单个字节数组解压为另一个字节数组:

byte[] combined = Stream.of(array1, array2, array3) // or use Stream.builder
    .map(arr -> decompress(arr))
    .flatMapToInt(a -> IntStream.range(0,a.length).map(i -> a[i]))
    .mapToObj(i -> (byte) i)                        // boxes into a Byte
    .collect(Collectors.collectingAndThen(Collectors.toList(), Bytes::toArray))
  1. 管道以 Stream<byte[]> 开始,包含压缩数据
  2. map() 将每个压缩的 byte[] 转换为未压缩的 byte[]
  3. flatMapToInt() 从每个 byte[] 中获取字节并创建单个连续的原始整数流
  4. 每个 byte 暂时只是一个 int,因为在下一阶段它会将其转换为 mapToObj()
  5. 中的盒装 Byte
  6. 流以 List<Byte> 的集合结束,然后传递给 guava 的 Bytes.toArray() 以将其转换为一个连续的解压缩数据字节数组。