将对象序列化到本地文件时出现 StreamCorruptedException

StreamCorruptedException when serializing objects to local file

我有一个 Android 应用程序,可以用来存储有关您品尝的所有葡萄酒的有用信息(名称、年份、价格、质量如何...)。为了允许用户在彼此之间或在他们的不同设备之间交换信息,我有一个序列化机制,允许用户:

这很好用。

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

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

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

我对从 Bitmap 创建字节数组的方式进行了一些尝试,并不断减小大小,直到它最终起作用。我不知道为什么,但是当我的 .ser 文件达到 ~1.3Mo 时会触发异常。

因此,如果我以糟糕的质量导出所有图片,一切正常。如果我稍微增加一点,那么当导出文件变成 'too big' 时我会得到异常(小于 2 Mo 不是那么多 - 我的 SD 卡上有足够的免费 space ).

我试图在每次调用 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 序列化后,调用 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 中将最大宽度设置为 200px 并将质量设置为 5% 来避免异常。

如果有人能解释为什么这个异常发生在 1.3 Mo 障碍附近,那就太棒了。 提前致谢:)

开始使用了。我只是愚蠢到误读了我SD卡上可用的space,当没有space可写时抛出异常。