【问题标题】:Reading and writing objects via GZIP streams?通过 GZIP 流读取和写入对象?
【发布时间】:2012-08-27 08:24:22
【问题描述】:

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

我该如何解决这个问题?

【问题讨论】:

  • 你关闭了输出流吗?

标签: java stream compression gzip gzipinputstream


【解决方案1】:

您必须刷新并关闭您的输出流。否则,至少,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. 许多类型都不需要这种序列化

它比可序列化的同类产品更实惠,而且绝对压缩得更多。

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

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

替代序列化框架

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

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

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

我应该去:

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

【讨论】:

  • 哇,效果很好!谢谢您的帮助。我完全忘记了 BufferedOutputStream 对象应该在创建后刷新。
  • 有什么办法可以进一步压缩 SubImage 对象吗?该类有 4 个整数和一个整数数组作为实例变量。
  • 我已将我的消息添加到帖子中。希望对您有所帮助!
  • 非常感谢。真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多