将对象序列化为本地文件时StreamCorruptedException

时间:2015-01-28 15:36:42

标签: java android exception serialization

我有一个Android应用程序可以用来存储所有葡萄酒的有用信息(名称,年份,价格,有多好......)。为了允许用户在彼此之间交换信息或者在不同的设备上交换信息,我有一个序列化机制,允许用户:

  • 将所有葡萄酒导出到.ser文件
  • 选择要从任何此类文件导入的葡萄酒

这很好用。

但是,前段时间,我收到了一个请求,也可以导出可添加到Wine描述中的图片。所以我修改了我的Wine类(实现Serializable)来添加byte []属性。

这就是麻烦开始的地方:用图片导出我的葡萄酒时,我得到 StreamCorruptedException

java.io.StreamCorruptedException
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1528)
at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1481)
at [...].WineVectorSerializer$2.run(WineVectorSerializer.java:84)

我玩弄了一下我从Bitmap创建字节数组的方式并保持缩小尺寸,直到它最终起作用。我不知道为什么,但是当我的.ser文件达到~1.3Mo时会触发异常。

因此,如果我以蹩脚的质量导出所有图片,一切正常。如果我稍微增加它,那么当导出文件变得“太大”时我会得到异常。 (不到2 Mo就是那么多 - 我的SD卡上有足够的可用空间。)

我试图在每次调用writeObject之间添加一个Thread.sleep(1000),但它没有帮助。



代码示例

序列化为文件

FileOutputStream fos = new FileOutputStream(filename);
final ObjectOutputStream out = new ObjectOutputStream(fos);

for (Wine aWine: data) {

  try {
    aWine.loadImage();
    out.writeObject(aWine);
    out.flush();
  } 
  catch (IOException e) {
    Log.e("Serialize", "Error during export");
    exportError = true;
    handle.sendMessage(handle.obtainMessage());
    break;
  }
  finally {
    aWine.freeImage();
  }
  handle.sendMessage(handle.obtainMessage());
}
out.close();

在上面的代码段中,您可以看到我调用 loadImage() [请参阅下一个代码段]和 freeImage()。第一个:

  • 将光盘中的图像(如果存在,检查Wine中的imagePath属性)加载到Bitmap对象中
  • 将其转换为byte []以存储在Wine的某个属性中以进行序列化

在Wine序列化之后,对 freeImage()的调用将此byte []设置为null,以允许垃圾收集器释放一些内存并避免内存不足异常 - 这会出口300多张带图片的葡萄酒时必然会发生。

加载图像

public void loadImage() {
  set_imageBytes(null);
  if (_imagePath != null && _imagePath.length() > 0) {

      File aImageFile = new File(_imagePath);

      // Just to get the image size
      BitmapFactory.Options options = new BitmapFactory.Options();
      options.inJustDecodeBounds = true;
      BitmapFactory.decodeFile(aImageFile.getAbsolutePath(), options);

      // No more than 500px
      int largestEdge = Math.max(options.outHeight, options.outWidth);
      int ratio = largestEdge/500;

      options.inJustDecodeBounds = false;
      options.inSampleSize = ratio;
      Bitmap aBitmap = BitmapFactory.decodeFile(aImageFile.getAbsolutePath(), options);
      if (aBitmap != null) {
          Log.i("Serialize", "There is an image to serialize");
          ByteArrayOutputStream stream = new ByteArrayOutputStream();
          aBitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream);
          set_imageBytes(stream.toByteArray());
      }
  }
}

在上面的代码中,我设法通过在aBitmap.compress中将max width设置为200px并将质量设置为5%来避免异常。

如果有人能解释为什么这个异常发生在1.3 Mo屏障周围,那就太棒了。 在此先感谢:)

1 个答案:

答案 0 :(得分:0)

让它发挥作用。我只是愚蠢地误读了SD卡上的可用空间,当没有空间可以写入时抛出异常。