I'm trying to save the data of a JAVA program in a .db file but isn't working.
The following message error appears:
"java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(Unknown Source)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(Unknown Source)
at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
at java.io.ObjectInputStream.<init>(Unknown Source)
at server.server.main(server.java:27)
Running"
My program is a Client-Server model working with JAVA RMI. I have 2 clients, 2 interfaces and then multiple classes including a server class and an implementation class with all the methods.
The "save" method is in the implementation class as follows:
public void save() {
ObjectOutputStream out;
try {
out = new ObjectOutputStream(new FileOutputStream(new java.io.File("C:/Users/Myself/Desktop/Hospital.db")));
out.writeObject(this);
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
In the server class:
try {
ObjectInputStream in;
try {
in = new ObjectInputStream(new FileInputStream(new java.io.File("C:/Users/Myself/Desktop/Hospital.db")));
read = (implementation)in.readObject();
in.close();
System.out.println(read);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
read = new implementation();
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
read = new implementation();
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
read = new implementation();
e.printStackTrace();
}
The "save" method is then used in both clients.
The exception stack trace shows an enf of file while trying to read the object stream header. From this we can determine several things:
the problems occurs while reading an object from file C:/Users/Myself/Desktop/Hospital.db. It does not happen while writing an object as your problem description seems to imply
the trace ObjectInputStream.readStreamHeader() shows that the stream is trying to read its header, so it happens at the beginning of the file. The stream header is normally made of 2 short values AC ED and 00 05, the first 4 bytes in the stream
the fact that EOFException is thrown before the stream header can be read implies that the stream has less than 4 bytes in it. I'll even bet it's empty. Why is it empty? It's impossible to know without seeing more of your code
So, in short: your code is trying to deserialize an object from an empty file, causing the exception you are observing.
Related
This question already has answers here:
java.io.FileNotFoundException when creating FileInputStream
(2 answers)
Closed 6 years ago.
For my application I want to use a Map to act as a database. To save and load a map, I am writing/reading it to/from database.ser using this 2 methods:
private synchronized void saveDB() {
try {
fileOut = new FileOutputStream(db);
out = new ObjectOutputStream(fileOut);
out.writeObject(accounts);
fileOut.close();
out.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
#SuppressWarnings("unchecked")
private void loadDB() {
try {
fileIn = new FileInputStream(db);
in = new ObjectInputStream(fileIn); // that is where error is produced if fileIn is empty
accounts = (Map<String, Client>) in.readObject();
in.close();
fileIn.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I want to load into Map when application starts, so I invoke method in constructor like this:
protected DriveatorImpl() {
accounts = new ConcurrentHashMap<String, Client>();
db = new File("C:/Users/eduar/git/Multy-Threaded-Bank-System/Bank-Services/database.ser");
// also, any suggestions how can I make path to a file more flexible in case I want to run Server side of an app on different machine?
if (!db.exists()) {
try {
db.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
loadDB(); // loads database when server start
}
I am aware of what causing an error, but I don't know what should I change in my design to avoid ObjectInputStream constructor receiving empty stream!
Any suggestions on what I can do differently?
Edit: I want to note that in fresh application run database.ser is empty since there was no entries made into Map yet.
Thank You!
First why the EOFExcpetion occur?
There are no contents in file or file is empty and you tried to read file.
You can avoid the EOFException for an empty file by checking file content length if it is less than or equal to zero means file is empty. another way to check if file is empty
Some code change and it worked for me.
#SuppressWarnings("unchecked")
private void loadDB() {
try {
if (db.length() <= 0) {
// if statement evaluates to true even if file doesn't exists
saveDB(); // save to a file an empty map
// if file doesn't exist, it creates a new one
// call loadDB inside constructor
}
FileInputStream fileIn = new FileInputStream(db);
ObjectInputStream in = new ObjectInputStream(fileIn); // that is where error is produced if fileIn is empty
in.readObject();
in.close();
fileIn.close();
System.out.println(accounts);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Get rid of the file.exists()/file.createNewFile() crap. All it is doing for you is masking the original FileNotFoundException problem, and turning into a thoroughly predictable EOFException because of trying to construct an ObjectInputStream around an empty stream. Handle the original problem. Don't just move it, or turn it into something else.
I have a program that needs to load data at launch. The data comes from a serialized object. I have a method loadData(), which is called upon construction of the Data class. Sometimes, (I.e. after a loss of saveData, or on first program launch on a new system), the file can be empty. (The file will exist though, the method ensures that).
When I try to run the program, I recieve an EOFException. So, in the method, I try to catch it, and just print a line to the console explaining what happened and return to the caller of the method. (so, upon return, the program will think loadData() is complete and has returned. However, it still crashes throwing the exception without printing a line to the console or anything. It is like it is totally ignoring the catch I have in place.
CODE:
protected void loadData()
{
// Gets/creates file object.
saveFileObject = new File("savedata.ser");
if(!saveFileObject.exists())
{
try
{
saveFileObject.createNewFile();
}
catch(IOException e)
{
System.out.println("Uh oh...");
e.printStackTrace();
}
}
// Create file input stream
try
{
fileIn = new FileInputStream(saveFileObject);
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
// Create object input stream
try
{
inputStream = new ObjectInputStream(fileIn);
}
catch(IOException e)
{
e.printStackTrace();
}
// Try to deserialize
try
{
parts = (ArrayList<Part>)inputStream.readObject();
}
catch(EOFException e)
{
System.out.println("EOFException thrown! Attempting to recover!");
return;
}
catch(ClassNotFoundException e)
{
e.printStackTrace();
}
catch(IOException e)
{
e.printStackTrace();
}
// close input stream
try
{
inputStream.close();
}
catch(IOException e)
{
e.printStackTrace();
}
}
Any help please?
Try writing your code like :
protected void loadData() {
// Gets/creates file object.
saveFileObject = new File("savedata.ser");
try {
if (!saveFileObject.exists()) {
saveFileObject.createNewFile();
}
// Create file input stream
fileIn = new FileInputStream(saveFileObject);
// Create object input stream
inputStream = new ObjectInputStream(fileIn);
// Try to deserialize
parts = (ArrayList<Part>) inputStream.readObject();
// close input stream
inputStream.close();
} catch (EOFException e) {
System.out.println("EOFException thrown! Attempting to recover!");
} catch (IOException e) {
System.out.println("Uh oh...");
e.printStackTrace();
}
}
Also note that EOFException is a sub-class of IOException
How about making one try and then making catches respectively like here?
This question already has answers here:
How to prevent InputStream.readObject() from throwing EOFException?
(3 answers)
Closed 9 years ago.
I can't seem to find a way to make readObject() transfer it's contents to an object variable. When I step through the Load function I get to "temp = (HashMap) ois.readObject();" Before this line is executed I am able to see the HashMap's data that I've written with oos in the expressions window of Eclipse so I know the data is there, however when this line executes I'm jumped to the IOException catch with an EOF. From what I've read this is expected, but I have not found a way to catch the EOF (loops with available() and readObjectInt() did not work). I'm running this on an Android emulator. Any suggestions would be appreciated.
public void Save(Pottylog data)
{
try
{
FileOutputStream fos = openFileOutput("Plog", Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(data.get());
oos.close();
}
catch (FileNotFoundException ex)
{
ex.printStackTrace();
}
catch (java.io.IOException e)
{
e.printStackTrace();
}
}
public HashMap<String, Integer> Load()
{
HashMap<String, Integer> temp = null;
try
{
FileInputStream fis = openFileInput("Plog");
ObjectInputStream ois = new ObjectInputStream(fis);
temp = (HashMap<String, Integer>) ois.readObject();
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
return temp;
}
EOFException means you have reached the end of the stream. I don't know what you think you're seeing in the debugger, but there is no object there in the stream to be read. catch(EOFException exc) does work; at this point you should close the stream and exit the reading loop. Don't misuse available() as an end of stream test: that's not what it's for.
I am trying to revise a java code to write something into a txt file. The original code is:
try {
out = new PrintStream(system.out, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
I use FileOutputStream to do this, and revise the code to:
try {
FileOutputStream os = new FileOutputStream("wiki.txt", true);
out = new PrintStream(os, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
But it doesn't work, the error is:
Wikipedia2Txt.java:56: unreported exception java.io.FileNotFoundException; must be caught or declared to be thrown
FileOutputStream os = new FileOutputStream("wiki.txt");
^
1 error
I try two ways: 1, I make a wiki.txt file manually on disk; 2, no wiki.txt exist before run the code.
But either doesn't work. It just stopped when compiled.
So what is going on?
Thanks.
Java is not telling you that the file is not found, just that it may not be found at runtime, and your program is not ready to handle it.
Here is one way to address this:
try {
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException fnf) {
// TODO Auto-generated catch block
fnf.printStackTrace();
}
Here is another way:
try {
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (IOException e) {
// TODO Auto-generated catch block
fnf.printStackTrace();
}
The first way ensures the compiler that your code is prepared to handle both exceptions separately; the second way ensures the compiler that your code is prepared to handle a superclass of both exceptions. The two ways are not the same, because the second one covers more exceptions that the first one.
Finally, there is an alternative to silence the compiler by declaring your function with a throws block (either a common superclass or the two individual classes would do). This is a way to tell the compiler that your function has no idea of how to handle these exceptions, and that they should be handled by a caller. The consequence of this approach is that every caller of your function must put a try/catch around the call, or declare the exceptions using throws.
The signature of the FileOutputStream constructor that you're using is public FileOutputStream(File file) throws FileNotFoundException. This means it is a checked exception which you have to handle. Therefore make sure that your method in which you have written this code either handles this exception (i.e. specify this exception as part of the catch block) or you specifically throw this exception.
So either of the following would work for you:
Specify in catch block
try {
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Or make your method throw this exception - so your method signature would be something like return_type method_name (params_list) throws FileNotFoundException
You need to handle the situation when the file is not found.
Try this:
try {
File file = (..your code..)
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// Handling a situation when file is not found.
e.printStackTrace();
}
Your IDE (for instance Eclipse, IDEA, NetBeans) should provide additional help in such situations. As you have generated stubs, you are probably already using IDE. Isn't your code red-underlined?
You are just trampling upon one of the sore spots of Java: checked exceptions. There's a myriad of exceptions that may happen when your code is running, but only some of them must be declared in advance. My preferred way to handle your piece of code would be to wrap any and all checked exceptions into a RuntimeException that you can handle somewhere else up the stack trace:
try {
FileOutputStream os = new FileOutputStream(file, true);
out = new PrintStream(os, true, "UTF-8");
} catch (RuntimeException e) {
throw e;
}
catch (Exception e) {
throw new RuntimeException(e);
}
In most cases handling exceptions right at the spot where they happen is wrong and leads to swallowed exceptions and generally unreliable, hard-to-debug code.
In a well-engineered application all exceptions that represent a failure—rather than an expected alternative situation—must be propagated up the stack frame towards the so-called exception barrier, where all failures are uniformly handled.
I have three classes, the client, the server and the handler (which is going to handle the server connections) as I show below:
// The Client
public void sendSomePackage() {
try {
socket = new Socket("localhost", 54321);
sos = socket.getOutputStream();
oos = new ObjectOutputStream(sockOutput);
} catch (IOException e) {
e.printStackTrace(System.err);
return;
}
// About to start reading/writing to/from socket
try {
Package package = new Package(100);
oos.writeObject(pacote);
} catch (IOException e) {
e.printStackTrace(System.err);
}
try {
Thread.sleep(50);
} catch (Exception e) {
e.printStackTrace();
}
// Done reading/writing to/from socket, closing socket.
try {
sock.close();
} catch (IOException e) {
System.err.println("Exception closing socket.");
e.printStackTrace(System.err);
}
//Exiting
}
Now the server class:
// The Server - with a method that just wait for connections
public void waitForConnections() {
while (true) {
try {
socket = serverSocket.accept();
// Server:Accepted new socket, creating new handler for it
SimpleHandler handler = new SimpleHandler(socket);
handler.start();
// Server:Finished with socket, waiting for next connection
}
catch (IOException e){
e.printStackTrace(System.err);
}
}
}
My handler, which just handle the server connections:
#Override
public void run() {
//Handler: Handler run() starting
while (true) {
try {
package = (Package) ois.readObject();
if (pacote != null) {
System.out.println("Package received " + pacote.getSourceid());
}
} catch (Exception e) {
e.printStackTrace(System.err);
break;
}
}
try {
// SimpleHandler:Closing socket
sock.close();
ois.close();
} catch (Exception e) {
// Handler: Exception while closing socket, e=" + e);
e.printStackTrace(System.err);
}
}
The idea is the client send some 'package' object to my server which is going to keep running receiving the 'package' object any time.
The connection works fine, but in the end of the program an exception is launched, this is the one:
Package received 100
java.io.EOFException
at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Unknown Source)
at java.io.ObjectInputStream.readObject0(Unknown Source)
at java.io.ObjectInputStream.readObject(Unknown Source)
at br.ufscar.socket.SimpleHandler.run(SimpleHandler.java:45)
at java.lang.Thread.run(Unknown Source)
I already search for something on Google but nothing so far.
Any idea ?
This is working exactly as you want it to (probably). It reads the 100 then goes through the loop again (while(true) never stops looping until a break statement) and throws an exception because no more data has been sent and it goes to the catch statement and prints the error before exiting your while loop.
EOFException ist an IOException that indicates the end of an stream.
Here we say that if there aren't any more bytes to read then we should break out of the while loop before trying to read the object, etc.
while (true) {
if (ois.read() == -1) break;
//...rest of the code
}
Ok, this is how object streams work and the solution that works everywhere.
Object stream data is preceded by a 4 byte 'magical' sequence AC ED 00 05. An ObjectInputStream will peek for this data at construction time rather than before the first read. And that's logical: one wants to be sure it is a proper stream before being too far in an application. The sequence is buffered by the ObjectOutputStream at construction time so that it is pushed on the stream at the first write.
This method gives rise to complexities in buffered situations or transferring via sockets.
Fortunately there is a just as simple as effective solution to all these problems:
Flush the ObjectOutputStream immediately after construction!
ObjectOutputStream myStream = new ObjectOutputStream ( anotherStream );
myStream.flush();