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
相关产品推荐
相关产品推荐

