[Logo]
Forums Register Login
How can I read all objects in a file with ObjectInputStream?
Hi people. I saw an example in Head First - Java that some objects are read from a file with ObjectInputStream. It's like this:


I need to do it in a loop (like for or while) because I don't now how many objects the file haves.
Is it possible? How can I do it?

Thanks.

Dadonas
Hi, welcome to the ranch!

Give it a try in a loop and see what happens when you try to read past the last object.

Hint: expect an exception. Note the exact exception class and look up the JavaDoc.

BTW: It is kind of the ranch style to give you some hints and set you off to experiment. The more you find on your own the more you will remember. Have fun, let us know what you find!
Hi friend Stan. Your hint was my first idea but I wanted a professional opinion. Below the solution:


Thanks for help me.
It looks from the doc that the library forces us to use try catch for normal expected logic. This is generally a pretty bad thing, but I don't see any other way. Anyone else?
Stan, I think your hint is the unique way, but the class ObjectInputStream should have a method like hasNext(). Don't you think?
I'm not a fan of using exceptions to handle expected events, as is apparently the case with ObjectInputStream. What I usually do when faced with this situation is put all my objects in a collection and serialize the collection. Of course, with large numbers of objects this method could cause performance problems.
Accurately, Joe. That's it!!!

Thank you so much.

Dadonas
Note that a stream is a stream, and you don't have to restrict your stream to holding just serialized objects. You could, for example, write the number of objects to follow as a four-byte int first (using DataOutputStream, for example.) Then read that word before trying to read any objects from the stream.
Neat! I suppose one could also put a delimiter or eof marker after each object if you don't know the number before you start writing.
Yeah, all ideas are welcome, but in my case, serialize an array is the way. I'm serializing objects to a file then after insert them in Oracle in other desktop. I'm using DAO, then I have an Interface like the exemplo bellow:

http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html

I read the information from my Oracle, serialize the informatiion, send the file to the other desktop, unserialize the objects an insert in the other Oracle.
I know it's not the best way, but they want it.

One more time, very thanks.
[Stan]: It looks from the doc that the library forces us to use try catch for normal expected logic. This is generally a pretty bad thing, but I don't see any other way. Anyone else?

I usually write and read an int first, as EFH suggests. Or write a Collection or array of objects at once. But if you don't have them all in memory at the start, or don't know in advance how many objects there will be, you could also do something like this:


[Joe]: What I usually do when faced with this situation is put all my objects in a collection and serialize the collection. Of course, with large numbers of objects this method could cause performance problems.

It could, but it's pretty much the same problem you'd have with any other technique suggested so far. The objects will all have to be in memory at once anyway, since the ObjectInputStream keeps a reference to everything it has deserialized so far. So there's no way you can save memory by processing one object and then discarding it, unless you close one stream and start a new one. Which adds more overhead in various forms. And the memory used by an ArrayList of objects, or an array of those same objects, is generally pretty close to the memory used by the objects themselves. I tried serializing 1000 Integer objects in various forms to see how much space they took:

ArrayList of Integers: 10125 bytes
Integer[] array: 10112 bytes
writeInt(1000) followed by 1000 Integers: 10077 bytes
1000 Integers followed by an EndOfStreamSignal: 10105 bytes

In the case of Integers I could have made it smaller by writing ints instead, but the point was to use a simple small object. For larger objects (or a larger number of objects, the type of container you use will matter even less (proportionately).

[EFH]: You could, for example, write the number of objects to follow as a four-byte int first (using DataOutputStream, for example.)

Minor clarification - an ObjectOutputStream implements DataOutput, an interface also implemented by DataOutputStream. As a result, an ObjectOutputStream already has a writeInt() method and many similar methods - there's no need to use a DataOutputStream also. Likewise ObjectInputStream has a readInt(), just like DataInputStream does. So writing and reading ints as EFH suggests is extremely easy.
Hi,

when i tried this below loop



times.add(..) gives nullpointer exception.
If i run //tim2 = (PersistentTime)in.readObject();

this line read the object in tim2 variable.

Also how while(true) loop will break?
i guess when it enters into exception,it should stop. But i have tried and its is running infinite times.
Use "break" inside the loop and first check weather readObject() returns null of not then add it into the List..

thanks
 

Ishan Pandya wrote:Use "break" inside the loop and first check weather readObject() returns null of not then add it into the List..


That is good practice but it's not why there is a NullPointerException, you can add nulls to an ArraylList. The problem is there is no ArrayList object only a variable of type ArrayList.

should be (including the generic notation)


@isha krishnan When you have a question please start your own thread, do not just append your question onto an old thread.
I am using the "fis.available() > 0" condition.

Is this a valid solution?
Welcome to CodeRanch Andrea!

I'm afraid not. InputStream.available() does not give a reliable file size. Instead, just loop until readObject() returns null.
No it's not a valid solution.

available() returns the number of bytes that can be read without blocking. If it returns 0 it does not mean the end of the stream has been reached it just means there are currently no more bytes available to read. This could be due to i/o delays, network delays etc.

Using available() in this way may appear to work every time when the file is stored locally but there are no guarantees. In short it's extremely bad practice to do this.
Thank you for your pointers about not using .available().
Using  CountingInputStream of Apache commons-io, I created a class CountingFileInputStream, which calls File.length() during construction and then provides a .remaining() method, which returns the number of bytes not yet read.
Would now using

be a valid solution?
I am asking out of curiosity, as the solution of using an EndOfStreamSignal class is valid for me.
Why would you want to do this and not the regular solution?
Wink, wink, nudge, nudge, say no more ... https://richsoil.com/cards


This thread has been viewed 37998 times.

All times above are in ranch (not your local) time.
The current ranch time is
Jun 25, 2018 11:58:39.