You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java读取GZIP文件为String后解压报错:Not in GZIP format求助

问题:GZIP压缩文件转String后解压失败,报Not in GZIP format错误

我尝试将GZIP压缩文件的内容读取到内存中作为String,再进行解压,但执行时抛出错误。确认文件是合法的GZIP格式且未损坏,且实际场景只能用String中转,不能直接用FileInputStream。相关代码及错误信息如下:

读取文件代码

/**
 * Read file content into a String
 */
private static String readUsingFileInputStream(String fileName) {
    FileInputStream fis = null;
    byte[] buffer = new byte[10];
    StringBuilder sb = new StringBuilder();
    try {
        fis = new FileInputStream(fileName);

        while (fis.read(buffer) != -1) {
            sb.append(new String(buffer));
            buffer = new byte[10];
        }
        fis.close();

    } catch (IOException e) {
        //...
    }
    return sb.toString();
}

解压代码

/**
 * Unzip file content
 */
public static String unzip(final byte[] compressed) {
    try (final GZIPInputStream gzipInput = new GZIPInputStream(new ByteArrayInputStream(compressed));
         final StringWriter stringWriter = new StringWriter()) {
        IOUtils.copy(gzipInput, stringWriter, UTF_8);
        return stringWriter.toString();
    } catch (IOException e) {
        throw new UncheckedIOException("Error while decompression!", e);
    }
}

调用代码

String compressedData = readUsingFileInputStream("/path/to/my/compressed_file_json.gz");
System.out.println(unzip(compressedData.getBytes(UTF_8)));

错误堆栈

java.util.zip.ZipException: Not in GZIP format
    at java.base/java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:166)
    at java.base/java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:80)
    at java.base/java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:92)

错误原因

核心问题是二进制压缩数据不能直接转成String存储:

  • String是用于存储文本数据的类型,依赖字符编码(如UTF-8)映射字节序列。但GZIP压缩后的二进制数据包含大量无法被UTF-8等编码正确映射的字节,直接转String时会出现字节丢失、乱码,后续调用getBytes(UTF_8)还原的字节数组已和原始压缩数据不一致,导致GZIPInputStream无法识别格式。
  • 原读取方法还存在额外问题:fis.read(buffer)返回的实际读取字节数未被利用,最后一次读取不足10字节时,buffer里的默认0值字节会被追加到String中,进一步污染原始数据。

修正方案

既然必须用String中转,需用Base64编码将二进制压缩数据转换成合法字符串,保证转String和还原字节数组时无数据丢失。

1. 修改读取方法:二进制数据转Base64字符串

private static String readUsingFileInputStream(String fileName) {
    FileInputStream fis = null;
    try {
        fis = new FileInputStream(fileName);
        // 读取全部字节并转成Base64字符串(Java 9+支持readAllBytes(),Java 8可改用IOUtils.readBytesFromStream(fis))
        byte[] allBytes = fis.readAllBytes();
        return Base64.getEncoder().encodeToString(allBytes);
    } catch (IOException e) {
        e.printStackTrace();
        return "";
    } finally {
        if (fis != null) {
            try {
                fis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

2. 修改解压方法:Base64字符串还原为字节数组后解压

public static String unzip(final String base64Compressed) {
    byte[] compressed = Base64.getDecoder().decode(base64Compressed);
    try (final GZIPInputStream gzipInput = new GZIPInputStream(new ByteArrayInputStream(compressed));
         final StringWriter stringWriter = new StringWriter()) {
        IOUtils.copy(gzipInput, stringWriter, StandardCharsets.UTF_8);
        return stringWriter.toString();
    } catch (IOException e) {
        throw new UncheckedIOException("Error while decompression!", e);
    }
}

3. 修改调用代码

String compressedData = readUsingFileInputStream("/path/to/my/compressed_file_json.gz");
System.out.println(unzip(compressedData));

内容的提问来源于stack exchange,提问作者HelloWorld

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 05:46:40