问题
As the title suggests, I'm trying to save to file an object that contains (among other variables, Strings, etc) a few BufferedImages.
I found this: How to serialize an object that includes BufferedImages
And it works like a charm, but with a small setback: it works well if your object contains only ONE image.
I've been struggling to get his solution to work with more than one image (which in theory should work) but each time I read the file in, I get my object back, I get the correct number of images, but only the first image actually gets read in; the others are just null images that have no data in them.
This is how my object looks like:
class Obj implements Serializable
{
transient List<BufferedImage> imageSelection= new ArrayList<BufferedImage>();
// ... other vars and functions
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeInt(imageSelection.size()); // how many images are serialized?
for (BufferedImage eachImage : imageSelection) {
ImageIO.write(eachImage, "jpg", out); // png is lossless
}
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
final int imageCount = in.readInt();
imageSelection = new ArrayList<BufferedImage>(imageCount);
for (int i=0; i<imageCount; i++) {
imageSelection.add(ImageIO.read(in));
}
}
}
This is how I'm writing and reading the object to and from a file:
// writing
try (
FileOutputStream file = new FileOutputStream(objName+".ser");
ObjectOutputStream output = new ObjectOutputStream(file);
){
output.writeObject(myObjs);
}
catch(IOException ex){
ex.printStackTrace();
}
// reading
try(
FileInputStream inputStr = new FileInputStream(file.getAbsolutePath());
ObjectInputStream input = new ObjectInputStream (inputStr);
)
{myObjs = (List<Obj>)input.readObject();}
catch(Exception ex)
{ex.printStackTrace();}
Even though I have a list of objects, they get read in correctly and each element of the list is populated accordingly, except for the BufferedImages.
Does anyone have any means of fixing this?
回答1:
The problem is likely that ImageIO.read(...)
incorrectly positions the stream after the first image read.
I see two options to fix this:
Rewrite the serialization of the
BufferedImage
s to write the backing array(s) of the image, height, width, color model/color space identifer, and other data required to recreate theBufferedImage
. This requires a bit of code to correctly handle all kinds of images, so I'll skip the details for now. Might be faster and more accurate (but might send more data).Continue to serialize using
ImageIO
, but buffer each write using aByteArrayOutputStream
, and prepend each image with its byte count. When reading back, start by reading the byte count, and make sure you fully read each image. This is trivial to implement, but some images might get converted or lose details (ie. JPEG compression), due to file format constraints. Something like:private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); out.writeInt(imageSelection.size()); // how many images are serialized? for (BufferedImage eachImage : imageSelection) { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); ImageIO.write(eachImage, "jpg", buffer); out.writeInt(buffer.size()); // Prepend image with byte count buffer.writeTo(out); // Write image } } private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { in.defaultReadObject(); int imageCount = in.readInt(); imageSelection = new ArrayList<BufferedImage>(imageCount); for (int i = 0; i < imageCount; i++) { int size = in.readInt(); // Read byte count byte[] buffer = new byte[size]; in.readFully(buffer); // Make sure you read all bytes of the image imageSelection.add(ImageIO.read(new ByteArrayInputStream(buffer))); } }
来源:https://stackoverflow.com/questions/32094497/serializing-an-object-that-includes-bufferedimages