将对象序列化到本地文件时出现 StreamCorruptedException
StreamCorruptedException when serializing objects to local file
我有一个 Android 应用程序,可以用来存储有关您品尝的所有葡萄酒的有用信息(名称、年份、价格、质量如何...)。为了允许用户在彼此之间或在他们的不同设备之间交换信息,我有一个序列化机制,允许用户:
- 将所有 Wines 导出到一个 .ser 文件中
- 选择要从任何此类文件导入的葡萄酒
这很好用。
然而,前段时间,我收到了一个请求,要求我也导出可以添加到 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 中的 imagePath 属性),则将其加载到位图对象中
- 将其转换为字节[]以存储在要序列化的 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 中将最大宽度设置为 200px 并将质量设置为 5% 来避免异常。
如果有人能解释为什么这个异常发生在 1.3 Mo 障碍附近,那就太棒了。
提前致谢:)
开始使用了。我只是愚蠢到误读了我SD卡上可用的space,当没有space可写时抛出异常。
我有一个 Android 应用程序,可以用来存储有关您品尝的所有葡萄酒的有用信息(名称、年份、价格、质量如何...)。为了允许用户在彼此之间或在他们的不同设备之间交换信息,我有一个序列化机制,允许用户:
- 将所有 Wines 导出到一个 .ser 文件中
- 选择要从任何此类文件导入的葡萄酒
这很好用。
然而,前段时间,我收到了一个请求,要求我也导出可以添加到 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 中的 imagePath 属性),则将其加载到位图对象中
- 将其转换为字节[]以存储在要序列化的 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 中将最大宽度设置为 200px 并将质量设置为 5% 来避免异常。
如果有人能解释为什么这个异常发生在 1.3 Mo 障碍附近,那就太棒了。 提前致谢:)
开始使用了。我只是愚蠢到误读了我SD卡上可用的space,当没有space可写时抛出异常。