在 Java 中使用 zlib 解压缩(不正确的 header 检查)

decompressing with zlib in Java (incorrect header check)

我尝试编程(并理解)compression/decompression。 我有一个用 zlib 压缩的文件,我认为我找到了解压缩我的文件的解决方案:

import java.util.Scanner;
import java.util.zip.*;
import java.io.*;

public class ZLibCompression
{
    public static void main(String args[])throws IOException, DataFormatException {
        File compressed = new File("./MyFile.hlb");
        
        decompress(compressed, new File("./MyFile.txt"));
        
    }
    
    public static void decompress(File compressed, File raw)
            throws IOException
    {
        try (InputStream inputStream = new InflaterInputStream(new FileInputStream(compressed));
             OutputStream outputStream = new FileOutputStream(raw))
        {
            copy(inputStream, outputStream);
        }
    }

 private static void copy(InputStream inputStream, OutputStream outputStream)
            throws IOException
    {
        byte[] buffer = new byte[1000];
        int length;

        while ((length = inputStream.read(buffer)) > 0)
        {
            outputStream.write(buffer, 0, length);
        }
    }
}

但我得到以下错误堆栈跟踪:

Exception in thread "main" java.util.zip.ZipException: incorrect header check
    at java.base/java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
    at java.base/java.io.FilterInputStream.read(FilterInputStream.java:106)
    at ZLibCompression.copy(ZLibCompression.java:46)
    at ZLibCompression.decompress(ZLibCompression.java:20)
    at ZLibCompression.main(ZLibCompression.java:11)

然后我检查了我文件的 header,它说:

{
 "compression" : {
  "crc32" : 2575274738,
  "decompressed_size" : 9020404,
  "type" : "zlib"
 },
 "encoded_data" : "eNrsvV2Xm0i

我的错误是什么?我发现一个 Python 脚本可以很好地处理同一个文件:

#!/usr/bin/env python
import sys
import os
import json
import base64
import zlib

SETLIST_OR_BUNDLE = "MyFile.hlb"

infile = open(SETLIST_OR_BUNDLE)
data = json.load(infile)
infile.close()

keys = list(data.keys())
if 'encoded_data' in keys:
    unz = zlib.decompress(base64.b64decode(data['encoded_data']))
    setlist_or_bundle = json.loads(unz)
    keys = list(setlist_or_bundle.keys())
    if 'setlists' in keys:
        setlists = setlist_or_bundle['setlists']
    elif 'presets' in keys:
        setlists = [setlist_or_bundle]
    for setlist in setlists:
        keys = list(setlist.keys())
        if 'meta' in keys:
            print()
            print("SETLIST: %s" % (setlist['meta']['name']))
        presets = setlist['presets']
        #print json.dumps(presets, indent=4)
        for preset in presets:
            if 'meta' in list(preset.keys()):
                meta = preset['meta']
                preset_name = meta['name']
                print("  ", preset_name)

我认为它与 base64 部分有关,我发现了一个类似的问题,其中有人提到“你必须先将 Base64 字符串解码为字节数组” - 好的 - 谁能解释一下或给我一个link 来个教程? 我所需要的只是 Java 中的相同功能,就像上面的 Python 脚本一样 - 当然我想学习一些东西......

首先,您的文件似乎没有被整体压缩。相反,它是一个包含实际压缩数据的 JSON-字符串 encoded_data。然后,您还需要解开 JSON-String 的包装。处理 JSON 加密数据的最简单方法是使用库。检查 this post 以了解不同库的一些比较。

接下来,正如您在 python 代码中看到的那样,编码数据在通过 ZLIB-Decompressor (zlib.decompress(base64.b64decode(data)))

之前从 Base64 解码

相当于 un-Base64 字符串的 java 是:

Base64.getDecoder().decode(string);