I am trying to read the contents of byte array created by gzipping an object, however when I try to unzip the contents of the byte array I get an error stating : java.io.EOFException: Unexpected end of ZLIB input stream
I am trying to use the try-with-resources idiom of java to manage the stream resources while compressing and decompressing an object, however if I add the ByteArrayOutputStream to the try-with-resources block another stream ObjectOutputStream fails to close.
I checked the implementation of ByteArrayOutputStream it extends AutoCloseable interface and even though its close isn't performing any work as such, it shouldn't have interfered with the closing of other resources.
Code I tried for compressing the object:
//This fails
public static byte[] returnCompressedObject(Object object) {
try(ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzOut = new GZIPOutputStream(out);
ObjectOutputStream objOut = new ObjectOutputStream(gzOut)) {
objOut.writeObject(object);
return out.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Error converting object to bytes ", e);
}
}
//This works with ByteArrayOutputStream moved out of try-with-resources block
public static byte[] returnCompressedObjectWithByteArrayOutside(Object object) {
//ByteArrayOutputStream moved out of try-with-resources block
ByteArrayOutputStream out = new ByteArrayOutputStream();
try(GZIPOutputStream gzOut = new GZIPOutputStream(out);
ObjectOutputStream objOut = new ObjectOutputStream(gzOut)) {
objOut.writeObject(object);
} catch (IOException e) {
throw new RuntimeException("Error converting object to bytes ", e);
}
return out.toByteArray();
}
//This works with explicit close being called on ObjectOutputStream
public static byte[] returnCompressedObjectWithExplicitClose(Object object) {
try(ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPOutputStream gzOut = new GZIPOutputStream(out);
ObjectOutputStream objOut = new ObjectOutputStream(gzOut)) {
objOut.writeObject(object);
//Explicit close being called on ObjectOutputStream
objOut.close();
return out.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Error converting object to bytes ", e);
}
}
Out of these returnCompressedObjectWithByteArrayOutside and returnCompressedObjectWithExplicitClose seem to return a byte array that I am able to use with below unzip method, but using returnCompressedObject before unzip ends up throwing exception java.io.EOFException: Unexpected end of ZLIB input stream during unzip Method used for unzipping:
public static String decompressUsingGZip(byte[] object) {
try(ByteArrayInputStream messageInputStream = new ByteArrayInputStream(object);
GZIPInputStream gzipStream = new GZIPInputStream(messageInputStream);
InputStreamReader inputStreamReader = new InputStreamReader(gzipStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(inputStreamReader)){
return reader.lines().collect(Collectors.joining());
} catch (IOException e) {
throw new RuntimeException("Error uncompressing object", e);
}
}
I am trying to understand why the returnCompressedObject isn't behaving as it should and closing the streams.
On searching the documentation I didn't find any place where it is mentioned that we shouldn't use ByteArrayOutputStream in try-with-resources.
Any help in understanding the cause of this behaviour is appreciated.