问题
I have a block of code, that deserializes multiple objects from file. How can i avoid using a while(true)?
ObjectInputStream in = new ObjectInputStream(new FileInputStream(
filename));
while (true) {
try {
MyObject o = (MyObject) in.readObject();
// Do something with the object
} catch (EOFException e) {
break;
}
}
in.close();
回答1:
You should write either a collection (with a size), or a put a marker before each object:
try {
for (;in.readBoolean();) {
MyObject o = (MyObject) in.readObject();
}
} catch (EOFException e) {
// ...
}
When you write your object, write a boolean just before (it will however take 1 byte if I do remember well that part):
for (MyObject o : iterable) {
out.writeBoolean(true);
out.writeObject(o);
}
out.writeBoolean(false);
If iterable
is a collection or map, you can use default serialization:
out.writeObject(iterable); // default collection serialization
Beside, don't catch an exception for each item, catch it globally (especially EOFException!): it is better for performance reasons.
I don't know if you work with Java 7, but your code + my for loop can be written like this:
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream( filename))) {
for (;in.readBoolean();) {
MyObject o = (MyObject) in.readObject();
}
} catch (EOFException e) {
// ...
}
// no need to close, the try-with-resources do the job for you.
回答2:
How can i avoid using a while(true)?
You can't.
More to the point, why do you think you want to?
This is a classic example of the tail wagging the dog. EOFException is thrown to indicate end of stream. Ergo you have to catch it, and ergo you have to loop until it is thrown, ergo you have to use while (true) or one of its cognates.
The exception thought police would have you prepend an object count, taking the curious position that external data structures should be designed to suit the coder's phobias, and overlooking that you may not know it in advance, or may need to change your mind, or may need to exit prematurely; or would have you write a null as an end-of-stream marker, overlooking that it prevents the use of null for any other purpose; and in both cases overlooking the fact that the API is already designed to throw EOFException, and already works the way it already works, so you already have to code accordingly.
回答3:
The code that I'm proposing let you to serialize and deserialize multiple objects really easily without having any problems and avoiding the awful (in my opinion) while true:
public class EntityClass implements Serializable{
private int intVal;
private String stringVal;
public EntityClass(int intVal, String stringVal) {
this.intVal = intVal;
this.stringVal = stringVal;
}
@Override
public String toString() {
return "EntityClass{" +
"intVal=" + intVal +
", stringVal='" + stringVal + '\'' +
'}';
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
EntityClass a = new EntityClass(1, "1");
EntityClass b = new EntityClass(2, "2");
EntityClass c = new EntityClass(3, "3");
ObjectOutputStream stream = new ObjectOutputStream(new FileOutputStream("out"));
stream.writeObject(a);
stream.writeObject(b);
stream.writeObject(c);
stream.close();
ObjectInputStream streamRead = new ObjectInputStream(new FileInputStream("out"));
EntityClass[] entities = new EntityClass[3];
int cont = 0;
try {
while (streamRead.available() >= 0) {
entities[cont] = (EntityClass) streamRead.readObject();
System.out.println(entities[cont]);
cont++;
}
} catch (EOFException exp) {
} finally {
streamRead.close();
}
}
}
来源:https://stackoverflow.com/questions/25361420/deserializing-multiple-objects-from-file-without-using-whiletrue