Temporary ObjectOutputStream wrapping InputStream

So I’ve been trying to figure out how to do this 100% correctly but I can’t find any good info.

Basically, I have a serialization function for a certain object, and that function takes in an OutputStream. This OutputStream may already have stuff written to it, and other things may be written to it after the serialization. Here’s the function:


	public void serializeTo(OutputStream output) throws IOException {
		ObjectOutputStream oos = new ObjectOutputStream(output);
		oos.writeObject(this);
		//WHAT DO I DO WITH oos NOW?!
		oos.flush();
	}

My question is: After creating the temporary ObjectOutputStream, I can’t close it once I’m done writing my stuff because that would close the underlying OutputStream. Is the correct thing to do here to only flush() it and then just leave it hanging?

Similarly, what do I do when I want to deserialize?


	public static GLSLFile deserializeFrom(InputStream input) throws IOException {
		ObjectInputStream ois = new ObjectInputStream(input);
		return (GLSLFile) ois.readObject();
		//I feel so dirty for not closing ois...
	}

Is this correct? Can this explode somehow? What am I supposed to do here?!

Why not use - OutputStream with Linked ByteBuffer Vise-Versa

Open close as many Streams as you want, you have same ByteBuffer )
simple take care about multiple threads usage same buffer :wink:

Extends OutputStream - add any count new position markers as you want)

Yes if data layout changed - let say you save objects with 10 bytes and in new(engine) version it have 15.
Data layout is important same as File (Objects) versions

i think its not best scenario to send InputStream to custom byte processor - when you can make custom InputStream class(Input/Output)

Just use what mother nature provided:


   public void serializeTo(OutputStream output) throws IOException {
+     ByteArrayOutputStream baos = new ByteArrayOutputStream();
      try(ObjectOutputStream oos = new ObjectOutputStream(baos)) {
         oos.writeObject(this);
      }
+     new DataOutputStream(output).writeInt(baos.size());
+     baos.writeTo(output); // pump buffered data into the output
   }

   public static GLSLFile deserializeFrom(InputStream input) throws IOException {
+     DataInputStream dis = new DataInputStream(input);
+     byte[] buf = new byte[someSanityCheck(dis.readInt())];
+     dis.readFully(buf);

+     try(ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(buf))) {
         return (GLSLFile) ois.readObject();
      }
   }

Yes it can explode, because ObjectInputStream is buffered, and may read beyond the boundaries of the object.
The code I provided in the previous reply doesn’t explode as much, they say.

Buffering of input streams is horrible :-\ ; it makes for fragile code and breaks the encapsulation of streams.

Contractually isn’t the only foolproof way of ‘temporarily’ using any buffered input stream(incl. OIS), to return it as a new wrapper of the passed in stream? Therefore requiring any subsequent reads to pass through the (potentially non-empty) buffer, and in so doing making the new stream permanent not temporary?

Though this obviously creates the potential for an ever increasing chain of streams & buffers due to multiple invocations.

Hmm… So I guess the simplest solution would be to simply change the Input/OutputStream parameters to ObjectInput/OutputStreams instead and let the user create the stream instead. That’ll be good enough for my usage right now…

Thanks for all the responses! Glad I could catch this error early. This really seems like a pretty major flaw in the stream design though…

you could avoid objectIO by using something better like xstream. you’re picking this for a special reason ?

Serializing “shader objects”. A byte[] for the code, a number of descriptor set definitions, other meta data about the shader. Just tedious to do it by hand for each class I have.

i see. fair enough.