Workaround java.io.EOFException cause by ObjectInputStream [duplicate] - java

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.

Related

How the FileOutputStream write properties file don't lost information

I found something wrong when I write the Properties file by using FileOutputStream.
public synchronized static void setProperties(String file,String Properties,String value)
{
try {
FileInputStream is = new FileInputStream(file);
Properties proper = new Properties();
proper.load(is);
proper.setProperty(Properties.toUpperCase(), value);
is.close();
FileOutputStream os = new FileOutputStream(file);
proper.store(os,"Update the file:"+Properties);
os.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Look at the two lines below:
FileOutputStream os = new FileOutputStream(file);
proper.store(os,"Update the file:"+Properties);
When the first line executed, the file will be empty, until the second line execute finished. Now, I assume the second line will execute within 3 seconds. During this period, the program crashed or another reason lead to the file to be unsuccessfully written. I will get an empty Properties file when I'm running my program next time. Anyone can tell me how to prevent this kind of situation to occur?
I changed my program like below, Seems it more better than before. At least I won't get a empty properties file, Thanks all guys.
public synchronized static void setProperties(String file,String Properties,String value)
{
try {
FileInputStream is = new FileInputStream(file);
Properties proper = new Properties();
proper.load(is);
proper.setProperty(Properties.toUpperCase(), value);
is.close();
proper.store(new FileOutputStream(file+".tmp"),"Update the file:"+Properties); //Prevent empty file
File old = new File(file);
File tmp = new File(file+".tmp");
if(tmp.exists() && tmp.length()>0)
{
old.renameTo(new File(file+".old"));
tmp.renameTo(new File(file));
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Java, Exception when trying to deserialize object, problems catching

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?

Save file with FileOutputStream does not create any file

Currently I'm developing an android app where the user has to click on a button this adds +1 to a count. After 100 there is another button which causes a reset of the count and increase the level and difficulty which is stored in another 2 "ints". Well its all working but I seriously have big problems with creating a save file.
-I gave me the permission via AndroidManifest.xml
-Tryed 3 other code examples
I did import everything that is necessary and the rest of the code is working
There has to be a mistake in this part of my code:
(my part for the Saving the "Stats")
save.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
try {
FileOutputStream savelvl = openFileOutput("savelvl.data", Context.MODE_PRIVATE);
savelvl.write(level);
savelvl.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
});
can anyone suggest an improvement to the code or tell me the mistake in saving the file to the internal storage?
I've had success with using a BufferedWriter instead of FileOutputStream, although I'm sure it could given a different setup. Below is some code with "FileOutputStream out", which I was trying to use initially, commented out.
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(file,true));
//out = new FileOutputStream(file);
Log.i("file","file opened");
writer.write(someString);
//out.write(someString.getBytes());
Log.i("file","file written");
} catch (Exception e) {
Log.e("fileNotFound","file not found exception");
e.printStackTrace();
}/*
try {
out.write(someString.getBytes());
Log.i("file","file written");
Log.i("str2File",someString.getBytes().toString());
} catch (IOException e) {
Log.e("fileWrite","file write error");
e.printStackTrace();
}*/ finally {
try {
//out.getFD().sync();
//out.close();
writer.close();
Log.i("file","file closed");
} catch (Exception e) {
Log.e("closeError","error closing file");
e.printStackTrace();
}
}
You cannot flush your data. When you use writer you must call flush method after write method.
OutputStrem stream = ... // I cannot create new reference because "OutStream" class is abstract
stream.write(data, offset, length);
stream.flush();
stream.close();

Reading from internal storage (deserialization)

I am using the following method to read from the internal storage:
private void deserialize(ArrayList<Alias>arrayList) {
try {
FileInputStream fis = openFileInput(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
arrayList = (ArrayList<Alias>)ois.readObject();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
It reads the content of the file "filename" to the "arrayList".
The "serialize" method is as follows:
void serialize(ArrayList<Alias>arrayList) {
FileOutputStream fos;
try {
fos = openFileOutput(filename, Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(arrayList);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
The problem is that I whenever I run my program again, the "arrayList" is empty. So I guess I am opening the file in wrong input mode.
My aim is to first get the array from the file, then modify it within the app, and then write the modified array back to the file.
Can someone please help me with my problem?
Thanks!
Can you post your pice of your source code? I think the way which you used to parse file content get issue.
Read here:
Android ObjectInputStream docs
I read that the method readObject() read the next object...i this that you must iterate with something like this:
MediaLibrary obj = null;
while ((obj = (MediaLibrary)objIn.readObject()) != null) {
libraryFromDisk.add(obj);
}

Java readObject previews data, but will not read or transfer it [duplicate]

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.

Categories