3

我是 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

我怎么解决这个问题?

4

1 回答 1

7

您必须刷新并关闭您的输出流。否则,至少,BufferedOutputStream不会将所有内容写入文件(为了避免惩罚性能,它会大量写入)。

如果你打电话compressedOutput.flush()compressedOutput.close()足够了。

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

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

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

更改序列化

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

只写你需要的

序列化的缺点是需要在您编写的每个实例之前编写“它是一个子图像”。如果您事先知道会发生什么,则没有必要。因此,您可以尝试更手动地对其进行序列化。

写你的列表,而不是写一个对象直接写符合你的列表的值。您只需要一个 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. 对于许多类型,您不需要这种序列化

它比 Serializable 对应物相当实惠且绝对压缩。

请记住,还有其他框架可以序列化对象或创建字符串消息(用于 xml 的 XStream、用于二进制消息的 Google 协议缓冲区等)。该框架可以直接处理二进制文件或编写可以写入的字符串。

如果你的应用需要更多关于这方面的信息,或者只是好奇,也许你应该看看它们。

替代序列化框架

刚刚查看 SO 并发现了几个解决此问题的问题(和答案):

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

我发现 XStream 使用起来非常简单直接。JSON 是一种非常易读和简洁的格式(并且兼容 Javascript,这可能是一个加号:)。

我应该去:

Object -> JSON -> OutputStreamWriter(UTF-8) -> GZippedOutputStream -> FileOutputStream
于 2012-08-27T10:53:50.043 回答