通过GZIP流读取和写入对象?

时间:2012-08-27 08:24:23

标签: java stream compression gzip gzipinputstream

我是Java新手。我想学习使用GZIPstreams。我已经尝试过了:

ArrayList<SubImage>myObject = new ArrayList<SubImage>(); // SubImage is a Serializable class

ObjectOutputStream compressedOutput = new ObjectOutputStream(
   new BufferedOutputStream(new GZIPOutputStream(new FileOutputStream(
   new File("....")))));
compressedOutput.writeObject(myObject);

ObjectInputStream compressedInput = new ObjectInputStream(
   new BufferedInputStream(new GZIPInputStream(new FileInputStream(
   new File("....")))));
myObject=(ArrayList<SubImage>)compressedInput.readObject();

当程序将myObject写入文件而不抛出任何异常,但是当它到达该行时

myObject=(ArrayList<SubImage>)compressedInput.readObject();

它抛出了这个异常:

Exception in thread "main" java.io.EOFException: Unexpected end of ZLIB input stream

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:6)

您必须刷新并关闭输出流。至少,BufferedOutputStream不会将所有内容都写入文件(为了避免影响性能,它会在大文件中写入)。

如果您拨打compressedOutput.flush()compressedOutput.close(),就足够了。

您可以尝试编写一个简单的字符串对象并检查文件是否写得很好。

如何?如果您编写xxx.txt.gz文件,可以使用首选的zip应用程序打开它,然后查看xxx.txt。如果应用程序抱怨,则内容未完整写入。

评论的扩展答案:压缩更多数据

更改序列化

如果SubImage对象是您自己的对象,则可以更改它的标准序列化。检查java.io.Serializable javadoc以了解如何操作。这很简单。

写出你需要的东西

序列化的缺点是需要在你编写的每个实例之前编写“它是一个SubImage”。如果你事先知道会有什么,那就没有必要了。所以你可以尝试更多地手动序列化。

要编写列表,而不是编写对象直接写入符合列表的值。你只需要一个DataOutputStream(但是ObjectOutputStream是一个DOS,所以无论如何都可以使用它。)

dos.writeInt(yourList.size()); // tell how many items
for (SubImage si: yourList) {
   // write every field, in order (this should be a method called writeSubImage :)
   dos.writeInt(...);
   dos.writeInt(...);
   ...
}

// to read the thing just:
int size = dis.readInt();
for (int i=0; i<size; i++) {
   // read every field, in the same order (this should be a method called readSubImage :)
   dis.readInt(...);
   dis.readInt(...);
   ...
   // create the subimage
   // add it to the list you are recreating
}

此方法更具说明性,但如果:

  1. 你知道将会写什么
  2. 对于许多类型
  3. ,您不需要这种序列化

    它非常实惠,并且比Serializable版本更加压缩。

    请记住,有序列化对象或创建字符串消息的替代框架(xSt的XStream,二进制消息的Google Protocol Buffers等)。该框架可以直接用于二进制或编写可以随后编写的字符串。

    如果你的应用需要更多,或只是好奇,也许你应该看看它们。

    替代序列化框架

    刚看了SO,发现了几个问题(和答案)解决了这个问题:

    https://stackoverflow.com/search?q=alternative+serialization+frameworks+java

    我发现XStream非常简单易用。 JSON是一种非常易读且易于使用的格式(与Javascript兼容,这可能是一个优点:)。

    我应该去:

    Object -> JSON -> OutputStreamWriter(UTF-8) -> GZippedOutputStream -> FileOutputStream