I am currently doing serialization in JAVA, As of now I have gotten the serializing and de-serializing working correctly. eg If I make a film in the program, close the program and then reopen the program the film will still be there. My problem is, even though all the code works and the serializing works correctly when I run the program I get this error as seen below.
Here you can see my program running and it showing the exception
Here is the code where the exception is pointing to
public void readRecordsFromFile()
{
Video v = null;
try
{
FileInputStream fileIn = new FileInputStream("PrintOut.dat");
ObjectInputStream in = new ObjectInputStream(fileIn);
while((v = (Video)in.readObject()) != null)
{
videos.add(v);
}
//videos=(ArrayList<Video>)in.readObject();
fileIn.close();
in.close();
}
catch(IOException i)
{
System.out.println("IO Exception");
i.printStackTrace();
return;
}
catch(ClassNotFoundException m)
{
System.out.println("Class Not Found Exception");
m.printStackTrace();
return;
}
}
And in particular it points to the line
while((v = (Video)in.readObject()) !=null)
Is there a way to remove the exception? The fact that my program runs fine even with the exception makes me believe that it maybe isn't that important but I feel it would be good practice to remove the exception.
Any help would be appreciated and if any of the other code is required just let me know,
Thanks in advance,
Jason
There's no really clean way to work out when the ObjectInputStream is going to hit the buffers.
Your best strategy is to start by writing an integer at the beginning to say how many objects you're going to write. Then, when you read objects back, you start by reading this integer in; then you read that many objects from the stream.
EOFException means you hit the end of the file and there's nothing to really deal with that. What I would recommend is adding a new catch for the EOFException to keep the error from showing up in your console. I would also move the close() calls to a finally block - so something like this:
public void readRecordsFromFile()
{
Video v = null;
try
{
FileInputStream fileIn = new FileInputStream("PrintOut.dat");
ObjectInputStream in = new ObjectInputStream(fileIn);
while((v = (Video)in.readObject()) != null)
{
videos.add(v);
}
//videos=(ArrayList<Video>)in.readObject();
}
catch(IOException i)
{
System.out.println("IO Exception");
i.printStackTrace();
return;
}
catch(ClassNotFoundException m)
{
System.out.println("Class Not Found Exception");
m.printStackTrace();
return;
}
catch(EOFException eofe)
{
// Don't print anything, we just don't want the error blowing up in the regular output.
return;
}
finally
{
// Guarantee that the streams are closed, even if there's an error.
fileIn.close();
in.close();
}
}
Related
My assignment is to save a list of employees as a binary file (and later read from it). I'm working on the output portion now, below is the block of the function that is in question. This function does have about 10 more lines but they edit things on the TextField arraylist.
The Employee class is the parent of both the Supervisor and Secretary classes. all is the ArrayList that holds all the employee, secretary, and employee objects.
I'm using netbeans 8.0.2, when the program runs and I click the save button in the gui (onActionEvent() is this function) there are no compiler errors. The "IO Error" or "No Permissions..." doesn't output. Ive tried saving both with and without the employees.dat file being already created.
I'm not really sure what to do at this point, I contemplated saving each object as a the collection of int, String, etc but that's dumb, it should be able to work this way... right?
EDIT:
Employee, Supervisor, and Secretary are all Serializable.
private void saveChanges(ArrayList<Employee> all, ArrayList<TextField> text, int index) {
try ( ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("employees.dat", true)); ) {
for (int i = 0; i < all.size(); i++) {
if (all.get(i).getClass() == (new Secretary().getClass()))
output.writeObject(new Secretary((Secretary) all.get(i)));
else if (all.get(i).getClass() == (new Supervisor().getClass()))
output.writeObject(new Supervisor((Supervisor) all.get(i)));
else
output.writeObject(new Employee(all.get(i)));
}
output.flush();
} catch (IOException io) {
io.printStackTrace();
} catch (SecurityException se) {
se.printStackTrace();
}
}
EDIT:
I have edited the try-catch to this code...
try ( ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("employees.dat", true)); ) {
output.writeObject(all);
output.flush();
output.close();
} catch (IOException io) {
io.printStackTrace();
} catch (SecurityException se) {
se.printStackTrace();
}
Still not writing to file. I have permissions in the folder the .java files are in.
try ( ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("employees.dat", true)); ) {
Change true to false, or remove it. You can't append to files created as object output streams, at least not like this, and it's debatable whether you're even supposed to be doing so.
for (int i = 0; i < all.size(); i++) {
if (all.get(i).getClass() == (new Secretary().getClass()))
output.writeObject(new Secretary((Secretary) all.get(i)));
else if (all.get(i).getClass() == (new Supervisor().getClass()))
output.writeObject(new Supervisor((Supervisor) all.get(i)));
else
output.writeObject(new Employee(all.get(i)));
}
Change this entire mess to this:
output.writeObject(all);
If this still doesn't work there must have been an exception somewhere, and you're just going to have to find it, print it, and post it. Edit it into your question. Or else you're looking at the wrong file.
NB you will also have to change the code that reads the file, to just read the list in a single readObject() call.
By any chance are you happening to write an applet or JNLP without appropriate permissions?
do you have write access to the folder that you are outputting the file ? (which in this case is the directory that the program is running in. )
I would recomend calling io.printStackTrace() and se.printStackTrace(); in the exception handlers to provide significantly more information about the exceptions.
At the end of the file writing also dont forget to call output.close() to ensure that the stream is closed properly, the tail of the data is written and there are no left over open file handles on your system.
EDIT: I uploaded some sourcecode here: http://stabbedbit.com/MCapp/
I'm having the problem with my stream that the client throws a StreamCorruptedException every other time.
For example:
first time: works fine -> exit client application.
second time: StreamCorruptedException -> exit client application.
third time: works fine -> exit client application.
forth time: StreamCorruptedException -> exit client application.
and so forth.
Here's the story (in short)
The server while(true) loops for clients, accepts them and if an accepted client quits the server's inputStream throws a Socket Exception which I catch and use to run this bit code:
if(dataSender != null) dataSender.stop();
if(dataReceiver != null) dataReceiver.stop();
try { if(output != null) output .close(); } catch(IOException e) { streamNotClosed("output"); }
try { if(input != null) input .close(); } catch(IOException e) { streamNotClosed("input"); }
try { if(cryptOut!= null) cryptOut .close(); } catch(IOException e) { streamNotClosed("encrypted output"); }
try { if(cryptIn != null) cryptIn .close(); } catch(IOException e) { streamNotClosed("encrypted input"); }
try { if(clientSocket != null) clientSocket.close(); }
catch(IOException e){ logger.warning(socketNotClosed); }
That all seems to work fine
The client and the server both use this bit of code for initializing streams:
cryptOut = new CipherOutputStream(clientSocket.getOutputStream(), protocol.encoder);
output = new ObjectOutputStream(cryptOut);
cryptIn = new CipherInputStream(clientSocket.getInputStream(), protocol.decoder);
input = new ObjectInputStream(cryptIn);
if all goes well a String is exchanged as handshake, the user gets verified and then input and output get forwarded to be handled by separate threads.
But when it doesn't the following error gets thrown at "input = new ObjectInputStream(cryptIn);"
java.io.StreamCorruptedException: invalid stream header: 81C69F13
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:801)
at java.io.ObjectInputStream.<init>(ObjectInputStream.java:298)
at com.stabbedbit.minecraftRemoteAdmin.desktop.connection.ConnectionManager.run(ConnectionManager.java:89)
at java.lang.Thread.run(Thread.java:722)
(The code it throws (81C69F13) is different every time)
I have tried solving this by calling the garbage collector when stopping the threads and closing the streams. But it without result. And I don't have any idea why else this could happening.
Edit: I also found out my server breaks if I connect a second client...
If anyone knows anything to help me out, Thanks in advance.
In your outputstream after you are done writing, flush() the stream. Also, check your Ciphers are properly initialized/reset in your code
Maybe you need to close the ObjectOutputStream code;
out.close();
I have a game that regularly saves the game current status to a file (by writing a serialized object to a file).The user can resume the game later on and it will read that object and build the game from there.
This seems to be working fine, but sometimes I get this exception
java.io.EOFException
at java.io.DataInputStream.readByte(DataInputStream.java:98)
at java.io.ObjectInputStream.nextTC(ObjectInputStream.java:506)
at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:778)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2003)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:1960)
at com.myGame.GameState.loadFromFile
at com.myGame.GameState.loadGame
And here is the loadFromFile code
try {
FileInputStream fis = mActivity.openFileInput(fileName);
ObjectInputStream is = new ObjectInputStream(fis);
stateDetails = (StateDetails)is.readObject();//exception is generated here
is.close();
fis.close();
} catch (Exception e) {
MyApplication.SWERR(e);
}
I don't understand why would this happen. Its one time object saving and reading. No loops involved to reach end of file. Why would it be generated?
Any help is appreciated ........thanks
Edit: this is how I do the saving
FileOutputStream fos = mActivity.openFileOutput(fileName, Context.MODE_PRIVATE);
ObjectOutputStream os = new ObjectOutputStream(fos);
os.writeObject(stateDetails);
os.flush();
fos.flush();
os.close();
fos.close();
This seems to be working fine, but sometimes I get this exception
Try to use this approach:
try {
FileInputStream fis = mActivity.openFileInput(fileName);
ObjectInputStream is = new ObjectInputStream(fis);
while(true) {
try {
stateDetails = (StateDetails) is.readObject();
}
catch(EOFException ex) {
is.close();
break;
}
}
}
catch (Exception e) {
MyApplication.SWERR(e);
}
I had similar problem and i solved it by code above. But always you need to make sure that:
don't call readObject() twice
close always ObjectOutputStream immediately after writing is done
if you are writing more objects at first you need to write their
count via writeInt(<value>) and then before reading call getInt() and read objects
in loop
EOFException means you are trying to read past the end of the file. Plausible causes could be:
Problem while writing the file, or possible corruption of the file itself.
It can be zero length file that shouldn't be zero length.
You might be reading a file, other than what was wrote.
My suggestion would be, put a check for is.available() and try reading the object.
I'm writing a small program for an assignment and part of it involves reading from a file using ObjectInputStream. I've run into a brick wall because I keep getting errors when trying to close the file in the finally block as well as a NullPointerException but I cannot understand why. Any help is much appreciated! I have checked already and the file path is correct, so it is able to find the file.
Example file:
hello || apples, acai berry, bananas || shopping || 0.0005 || yes
public Disease[] readInCancers() {
Disease[] cancerList = null;
try {
FileInputStream fis = new FileInputStream(myData);
BufferedInputStream bis = new BufferedInputStream(fis);
ois = new ObjectInputStream(bis);
while(true) {
Disease disease = null;
try {
disease = (Disease)ois.readObject();
} catch (EOFException eofx) {
break;
}
if (cancerList == null || cancerList.length == 0) {
cancerList = new Disease[1];
cancerList[0] = disease;
} else {
Disease[] newList = new Disease[cancerList.length + 1];
System.arraycopy(cancerList, 0, newList, 0, cancerList.length);
newList[cancerList.length] = disease;
cancerList = newList;
}
}
} catch (FileNotFoundException fnfx) {
JOptionPane.showMessageDialog(null, "File could not be found");
} catch (IOException iox) {
JOptionPane.showMessageDialog(null, "Problem with reading from file");
} catch (ClassNotFoundException cnfx) {
JOptionPane.showMessageDialog(null, "Class could not be found");
} catch (NullPointerException npx) {
System.out.println("blah");
} finally {
try {
ois.close();
} catch (IOException iox) {
JOptionPane.showMessageDialog(null, "Problem with closing file");
}
}
return cancerList;
}
When I run the program, it gives a NullPointerException at ois.close() as well as an IOException that produces the pop-up "Problem with reading from file".
I have also tried changing how the file itself is structured, replaced the || (delimiters) with a word or even blank space but nothing changes.
Your FileInputStream is throwing an exception (I'm guessing from incorrect file permissions, but you'll have to look into this further); this occurs before you initialize your ObjectInputStream, so ois is still null when you reach your finally block which is resulting in a null pointer exception. It's usually a good idea to precede close statements in final blocks by null pointer checks for this reason.
When using an ObjectInputStream the input data is required to be in a byte format that can be read into a serialized object, Disease in this case. If the format is not in the expected format a StreamCorruptedException will be thrown. If you are changing the text file manually, chances are that this exception is being thrown but the exact message is not displayed as you are displaying a generic Problem with reading from file message.
Displaying the stack trace will help
iox.printStackTrace();
Ensure that you are writing the objects correctly to file. Alternatively you could use a text based file, and use Printwriter to write, Scanner to read. You can use || for as a Scanner delimiter.
I serialize an object and save it as a file on my HDD. When I'm reading it, in only some occasions it throws EOFException. After couple of hours debugging I am not able to find a problem.
Here is my code:
public void serialize(MyClass myClass,String path) {
FileOutputStream foStream = null;
ObjectOutputStream ooStream = null;
try {
File file = new File(path);
if (!file.exists()) {
file.createNewFile();
}
foStream = new FileOutputStream(file);
ooStream = new ObjectOutputStream(foStream);
ooStream.writeObject(myClass);
} catch (Throwable t) {
log.error(t);
} finally {
if (ooStream != null) {
try {
ooStream.flush();
ooStream.close();
} catch (IOException e) {
log.error(e);
}
}
}
}
For getting Object:
public MyClass deSerialize(String path) {
MyClass myClass=null;
FileInputStream fiStream = null;
ObjectInputStream oiStream = null;
String errorMessage = "";
try {
File file = new File(path);
if (!file.exists()) {
return null;
}
fiStream = new FileInputStream(path);
oiStream = new ObjectInputStream(fiStream);
Object o = oiStream.readObject();
myClass = (MyClass) o;
} catch (Throwable t) {
log.warn(t);
} finally {
if (oiStream != null) {
try {
oiStream.close();
} catch (IOException e) {
log.error(e);
}
}
}
return myClass;
}
Stacktrace:
java.io.EOFException at
java.io.ObjectInputStream$BlockDataInputStream.peekByte(ObjectInputStream.java:2498)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1273)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
at java.util.LinkedList.readObject(LinkedList.java:776) at
sun.reflect.GeneratedMethodAccessor583.invoke(Unknown Source) at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585) at
java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:946)
at
java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1809)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1719)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
at
java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1908)
at
java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1832)
at
java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1719)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
Question:
My serialized object is now corrupted and then is it rubbish now?
Because this object is responsible for rendering the UI which saved by user. If User logs in it should render previously saved state of UI. However for some user the file cannot be deserialized.
EOFException means you are trying to read past the end of the file. Normally you don't have any way of knowing whethere there are more objects to read, other than trying it, so you shouldn't regard EOFException as a problem in the first place. If it is thrown in a situation where you think you know there are more objects in the file, e.g. when you have prefixed an object count to the file, it indicates a problem with the code that wrote the file, or possible corruption of the file itself. Another example is a zero length file that shouldn't be zero length. Whatever the problem is, it can't be solved by the reading end, it is already too late.
I cannot see any problem with the writing and reading of the file.
So my best guess is that the problem is at the file level. For example:
you could be writing one file and reading a different one, or
you could be reading the file before the file write completes, or
something else could be clobbering the file in between the running of your write code and read code.
I suggest that you add some tracing code that uses File.length() to find out what the file size is after you've written it and before you read it.
A couple of other possibilities:
the writer and reader code is using different versions of MyClass (or a dependent class) with incompatible representations and the same serialVersionId values, or
you could be using custom readObject and writeObject methods that are incompatible.
In my case, EOF Exception was solved by ensuring the read and writes to the file were thread safe. Like Stephen C answered above, if you try to write to a file which you also are trying to read from say from another thread, you may be stepping on the ObjectInputStream which is going to throw EOF Exception in this case.