I have a series of different object serialized into a binary file.How can I read the file until the end?
try {
ObjectInputStream reader = new ObjectInputStream(new FileInputStream(fname));
Object obj = reader.readObject();
if (obj instanceof Azienda) {
Azienda a = (Azienda) obj;
company.put(a.getCod(), a);
} else if (obj instanceof Privato) {
Privato p = (Privato) obj;
privato.put(p.getCod(), p);
}
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
} catch (FileNotFoundException ffe) {
System.err.println("Error: the file was not found!");
} catch (IOException ioe) {
ioe.printStackTrace();
}
in this way I read only once object per read.
when I read a text file I use null
try{
while(true) {
Object obj=reader.readObject()
// do sth with object
}
}catch(EOFException e){
//we expect it so ignore
}
there is no EOF check besides the exception when you read past it for ObjectInputStream so you'll have to use the code smell called exceptions for control flow
It seems that an EOFException is thrown when there is no more object to read from the stream. Unfortunately, it's not even documented. So, I see the following solutions:
you read in a loop until you get this exception,
you make it so that you know in advance the number of objects in the stream,
you make it so that there is a marker object which marks the last object of the stream,
you serialize (and unserialize) a unique object: a List<Object> containing all the objects. This last solution, of course prevents writing the objects on the fly to the stream, and forces you to have all the objects in memory before serializing them.
ObjectInputStream does not have a concrete method for checking for end-of-file.
But every read...() method of ObjectInputStream throws an EOFException when it tries to read past the end of file. Unfortunately this is not explicitly documented for readObject(), but it is for all the other methods (readInt() etc.)
http://docs.oracle.com/javase/7/docs/api/java/io/ObjectInputStream.html
ObjectInputStream reader = null;
try {
reader = new ObjectInputStream(new FileInputStream("sth"));
Object obj = null;
while ((obj = reader.readObject()) != null) {
System.out.println(obj);
}
} catch (EOFException e) {
System.out.println("finnished reading");
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
} catch (FileNotFoundException ex) {
System.err.println("Error: the file was not found!");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
reader.close();
}
Related
I have read other questions similar to this but didn't help much. So I have some serialized content in a file and I am trying to read it and print it on the console, content is getting printed fine but at the end, it's showing an EOFException. Is there any way to fix my code to avoid this exception?
try {
File file = new File("EnrolledStudentsSerial.txt");
FileInputStream fi = new FileInputStream(file);
ObjectInputStream input = new ObjectInputStream(fi);
while(true) {
System.out.println(input.readObject());
}
}
catch (IOException | ClassNotFoundException e) {
System.out.println("Error: " + e);
}
I don't think you want to 'avoid' this exception.
You need to know when you come to the end of the input, and the EOFException is what is telling you you've come to the end of the input.
Rather, you want to stop treating it as an error condition, since it is not an error, it is normal and expected.
try {
… code as before …
}
catch (EOFException e) {
// end of input, nothing to do here
}
catch (IOException | ClassNotFoundException e) {
System.out.println("Error: " + e);
}
Here is the code I have:
ObjectInputStream ois = null;
UserRegistration UR = new UserRegistration();
Scanner pause = new Scanner(System.in);
Admin go = new Admin();
try {
//ItemEntry book = new ItemEntry();
ois = new ObjectInputStream(new FileInputStream("Account.txt"));
while ((UR = (UserRegistration) ois.readObject()) != null) {
//if (book.getName().equals("1"))
{
System.out.println(UR);
}
}
} catch (EOFException e) {
System.out.println("\nEnd**");
}catch (ClassNotFoundException ex) {
System.out.println(ex.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
} finally {
try {
ois.close();
System.out.println("Press \"ENTER\" to continue...");
pause.nextLine();
go.startup();
} catch (Exception ex) {
System.out.println(ex.getMessage());
}
}
}
How can I make it drop out from the loop and not to straight enter to the EOFException when it reach the last object? Help please !
This is a duplicate of this question :
Java FileInputStream ObjectInputStream reaches end of file EOF
Bottom line is that ObjectInputStream does not return null when it reaches the end of the stream. Instead, the underlying FileInputStream throws an EOFException. Although you could interpret that as the end of file, it does not allow you to distinguish a truncated file. So, practically speaking, ObjectInputStream expects you to know how many objects you will be reading in.
To get around this you could write an integer to the start of the file indicating how many UserRegistration objects are in the file. Read that value, then use a for loop to read that many objects.
Alternatively, you may be able to serialize your UserRegistration objects as an array or other container and then de-serialize the whole array/container.
I created a new file roomChecker which is empty. Now when I read it, it throws me an EOFException which is undesirable. Instead I want it to see that, if file is empty then it would run other two functions that are in if(roomFeed.size() == 0) condition. I could write this statement in EOFException catch clause; but that's not what I want to do because then every time when the file will be read and reaches end of file it will execute those functions. Instead when the file has some data it should do what is specified in else.
File fileChecker = new File("roomChecker.ser");
if(!fileChecker.exists()) {
try {
fileChecker.createNewFile();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Unable to create new File");
}
}
try(FileInputStream fis = new FileInputStream("roomChecker.ser"); ObjectInputStream ois = new ObjectInputStream(fis)) {
roomFeed = (List<roomChecker>) ois.readObject();
System.out.println("End of read");
if(roomFeed.size() == 0) {
System.out.println("your in null if statement");
defaultRoomList();
uploadAvailableRooms();
} else {
for(int i=0; i<roomNumber.size(); i++) {
for(int j=0; j<roomFeed.size(); i++) {
if((roomNumber.get(i)).equals(roomFeed.get(i).getRoomNumSearch())){
System.out.println("Reach Dead End for now");
} else {
defaultRoomList();
uploadAvailableRooms();
}
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
All this:
if(!fileChecker.exists()) {
try {
fileChecker.createNewFile();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Unable to create new File");
}
}
is a complete waste of time, and it is one of two possible causes for your empty file problem. Creating a file just so you can open it and then get a different problem instead of coping correctly with the original problem of the file not being there isn't a rational strategy. Instead, you should do this:
if (fileChecker.isFile() && fileChecker.length() == 0) {
// file is zero length: bail out
}
and, in the following code, this:
try(FileInputStream fis = new FileInputStream(fileChecker); ObjectInputStream ois = new ObjectInputStream(fis)) {
// ...
}
catch (FileNotFoundException exc) {
// no such file ...
}
// other catch blocks as before.
Of course you can still get EOFException if you read the file to its end, or if the file is incomplete, and you still need to handle that.
The output is correct but it's followed by an EOFException. I read the documentation but still i don't know how to solve this
try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file.bin"))){
for(Ser s = (Ser)ois.readObject(); s!=null; s=(Ser)ois.readObject() )
System.out.println(s);
}catch (IOException | ClassNotFoundException e){
e.printStackTrace();
}
You are assuming that readObject returns null if there is no data, but in fact it throws EOFException. The simplest fix is just to catch the exception:
try(...) {
for(;;) {
Ser s = (Ser)ois.readObject();
System.out.println(s);
}
} catch(EOFException e) {
// normal loop termination
} catch(IOException | ClassNotFoundException e){
// error
}
Be aware that some people and coding standards consider it bad practice to have an exception thrown in non-error conditions, like reaching the end of input in this case.
Hi I have an issue when trying to append new objects to the existing file..
Once the android app has been lunched again I want to get the existing file and add a new objects then read the objects from the existing file ... Actually, when I'm trying to read the object, the code will read only the first objects .. You can find below the code .. Could you please help ? Thanks
using the following method to write an objects :
public void saveObject(Person p, File f){
try
{
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f, true));
oos.writeObject(p);
oos.reset();
oos.flush();
oos.close();
}
catch(Exception ex)
{
Log.v("Serialization Save Error : ",ex.getMessage());
ex.printStackTrace();
}
}
Using the following method to read an objects :
public Object loadSerializedObject(File f)
{
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(f));
try{
Object loadedObj = null;
while ((loadedObj = ois.readObject()) != null) {
Log.w(this.getClass().getName(), "ReadingObjects") ;
}
return objects;
}finally{
ois.close();
}
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
Unfortunately you can't create a new ObjectOutputStream every time you want to append to the stream and then read everything back with a single stream. The constructor adds headers to the underlying stream before you start writing objects. You are probably seeing the java.io.StreamCorruptedException: invalid type code: AC exception, that's because the first header is 0xAC.
I don't know how many objects you are dealing with, but one option might be to read all your objects and then rewriting them all using a single ObjectOutputStream. That can get pricy if there are lots of objects. Alternatively, you might want to consider managing the serialization yourself manually through Externalizable. It can get painful though.