Serializable ArrayList -- IOException error - java

The code below returns an IOException. Here's my main:
public class Main
{
public static void main(String[] args) {
Book b1 = new Book(100, "The Big Book of Top Gear 2010", "Top Gear",
"BBC Books", 120, "Book about cars.");
Book b2 = new Book(200, "The Da Vinci Code", "Dan Brown", "Vatican", 450,
"A fast paced thriller with riddles.");
Book b3 = new Book(300, "Le Petit Nicolas", "Sempe Goscinny", "Folio", 156,
"The adventures of petit Nicolas.");
ArrayList<Book> biblia = new ArrayList<Book>();
biblia.add(b1);
biblia.add(b2);
biblia.add(b3);
File f = new File("objects");
try {
FileInputStream fis = new FileInputStream("objects");
int u = fis.read();
if (u != -1) {
ObjectInputStream ois = new ObjectInputStream(fis);
Bookstore b = (Bookstore) ois.readObject();
ois.close();
} else {
Bookstore b = new Bookstore(biblia);
FileOutputStream fos = new FileOutputStream("objects");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(b);
oos.close();
}
} catch (FileNotFoundException ex1) {
System.out.println("File not found.");
} catch (IOException ex2) {
System.out.println("IO Error.");
} catch (ClassNotFoundException ex3) {
System.out.println("Class not found.");
}
}
This is the Bookstore class which I use just to store the ArrayList of Book objects in orded to use it in Object streams.
public class Bookstore implements Serializable {
private ArrayList<Book> myBooks = new ArrayList<Book>();
public Bookstore(ArrayList<Book> biblia) {
myBooks = biblia;
}
}
I've imported all the right libraries too.
What I try to do is: If the file is not empty, then read the ArrayList from there (the bookstore object that contains the arraylist). If it's empty write a new one.
The problem is that the only thing I get in returns is "IO Error." and I can't understand why.

It's wrong way to test if file exists. You are trying create stream from file which doesn't exists, and FileNotFoundException is thrown. Instead of:
FileInputStream fis = new FileInputStream("objects");
int u = fis.read();
if (u != -1) {
just use
if(f.exists()) { ... }

It would help you debug these problems if you printed the stack trace when you get an exception, but I am guessing that Book is not serializable.

Nightsorrow is probably right. To answer why you are getting "IO Error" out, it is because you told the program to print that if there was an IO Error. For the purposes of debugging your code I would delete the
catch (IOException ex2) {
System.out.println("IO Error.");
}
section of your code or comment it out so that you can get the stack trace. Then you can pinpoint where and why the error is occuring because it will give you an exception and what line that exception was thrown.

Related

Error While serializing arraylist. Getting NotSerializable Exception..Even after implementing Serializable

I'm trying to achieve the following...
I have an ArrayList of type class which stores class objects
each time it stores a new object I serialize it and wipe out the previous object.
I have methods like add search delete etc.
when I try to add I get then exception,
Exception Caught: java.io.NotSerializableException: java.io.BufferedReader
code:
public static ArrayList<Library> bookData = new ArrayList<Library>();
public void addBook()
{
objCount++;
try{
System.out.println("_________________Enter Book Details_________________");
System.out.println(" Enter title of the Book : ");
this.setBookTitle();
System.out.println(" Enter the Name of Author : ");
this.setBookAuthor();
System.out.println(" Enter the Subject of Book : ");
this.setBookSubject();
System.out.println(" Enter the Price of Book : ");
this.setBookPrice();
System.out.println(" Enter Number of Copies :");
this.setNoOfCopies();
FileOutputStream fos = null;
ObjectOutputStream oos = null;
try {
fos = new FileOutputStream("Database.ser");
oos = new ObjectOutputStream(fos);
oos.flush();
oos.writeObject(bookData);
oos.close();
fos.close();
}catch(Exception e){
System.out.println("Exception Caught: "+e);
}
}catch(IOException e){
System.out.println("IO Exception Caught: "+e);
}catch(Exception e){
System.out.println("Exception Caught: "+e);
}finally{
try{
File file = new File("Books_Index.txt");
FileWriter fw = new FileWriter(file, true);
int count=getObjCount();
fw.write("\nBook Index ["+count+"] Contains Book Named: ["+getBookTitle()+"]");
fw.close();
//saveData();
}catch(Exception e){
System.out.println("Exception Caught: "+e);
}
}
}
Which, I googled and got the answer as you need to implement serializable interface.
I have already implemented it.
What could be the reason. I'm sending code by sharing my pastebin link
Link: https://pastebin.com/Q8F3iwex
Classes that implement Serializable interface can be serialized. InputStreamReader and BufferedReader don't implement this interface.
Quick Solution is that:
protected transient InputStreamReader inputStream = new InputStreamReader(System.in);
protected transient BufferedReader scan = new BufferedReader(inputStream);
it serializes objects in an object recursively when you serialize the object,Every object must be serializable.From the source code in jdk,object which is a String,Array,Enum or an implementation of Serializable can be serialized.
source code in ObjectOutputStream
// remaining cases
if (obj instanceof String) {
writeString((String) obj, unshared);
} else if (cl.isArray()) {
writeArray(obj, desc, unshared);
} else if (obj instanceof Enum) {
writeEnum((Enum<?>) obj, desc, unshared);
} else if (obj instanceof Serializable) {
writeOrdinaryObject(obj, desc, unshared);
} else {
if (extendedDebugInfo) {
throw new NotSerializableException(
cl.getName() + "\n" + debugInfoStack.toString());
} else {
throw new NotSerializableException(cl.getName());
}
}
In your Library class,there is a BufferedReader field,it can not be serialized.
you can try this
transient BufferedReader scan = new BufferedReader(new InputStreamReader(System.in));
Or implement your own serialization logic like this:
private void writeObject(ObjectOutputStream out) throws IOException {
//your own serialization logic
.......
}
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
//your own deserialization logic
........
}

How to debug a Java serialization fault?

I was studying Java Serialization for the first time which said that it could save the Object's 'state'.
So I tried to make a simple Java console game which would create a new 'player' and set its default IQ to 80. And whenever they ran the game (i.e. run the main function) they will find that their IQ has increased by 1 from the previous time.
Here is my code:
IQIncreaser.java
package IQIcreaserGame;
import java.io.Serializable;
public class IQIncreaser implements Serializable {
private int iq;
public int getIq() {
return iq;
}
public void setIq(int iq) {
this.iq = iq;
}
#Override
public String toString() {
return "Your IQ is now: " + iq;
}
}
Main.java
package IQIcreaserGame;
import java.io.*;
public class Main {
public static void main(String[] args) {
IQIncreaser bakra = new IQIncreaser();
bakra.setIq(80);
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:/saveIQ.ser"));
oos.writeObject(bakra);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Welcome to the IQ increaser!!!");
System.out.println("Whenver you run this game your IQ will increase by 1!!");
System.out.println("Just check it out");
System.out.println("Your IQ at beginning was " +bakra.getIq() + ", come back for more");
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/saveIQ.ser"));
IQIncreaser restoredAndIncreased = (IQIncreaser) ois.readObject();
// Here I am increasing the IQ by one everytime the main runs
restoredAndIncreased.setIq(restoredAndIncreased.getIq()+1);
System.out.println("The increased IQ is " + restoredAndIncreased.getIq());
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Now the problem/confusion part:
Whenever I run the game i.e. everytime I run main() function I thought I would get a expected output in which the player's IQ would increase by 1 because it takes the "previous value" from the .ser saved file and adds 1 to it.
Like this the first default value is 80
Then on second run : 81
then on third run: 82
then on fourth run: 83.. and so on
But everytime I am getting 81 as the increased value. Where is the problem and what is the best way to fix this?
Please find the complete code below. Basically you need to ensure that you are overwriting the file one it has been created, else, you are restoring the IQ back to 80.
Finally ensure your serialize your object back to same filw after incrementing the IQ.
class IQIncreaser implements Serializable{
int Iq ;
public int getIq() {
return Iq;
}
public void setIq(int iq) {
Iq = iq;
}
}
public class Main {
public static void main(String[] args) {
Path path = Paths.get("/home/akshayap/saveIQ.ser");
//create default file only if it does not exist
if (Files.notExists(path)) {
IQIncreaser bakra = new IQIncreaser();
bakra.setIq(80);
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/home/akshayap/saveIQ.ser"));
oos.writeObject(bakra);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Welcome to the IQ increaser!!!");
System.out.println("Whenver you run this game your IQ will increase by 1!!");
System.out.println("Just check it out");
IQIncreaser restoredAndIncreased=null;
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("/home/akshayap/saveIQ.ser"));
restoredAndIncreased = (IQIncreaser) ois.readObject();
System.out.println("Your IQ at beginning was " +restoredAndIncreased.getIq() + ", come back for more");
// Here I am increasing the IQ by one everytime the main runs
restoredAndIncreased.setIq(restoredAndIncreased.getIq()+1);
System.out.println("The increased IQ is " + restoredAndIncreased.getIq());
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
//serialize the object into the same file post increment
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/home/akshayap/saveIQ.ser"));
oos.writeObject(restoredAndIncreased);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
update bakra.setIq also
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/saveIQ.ser"));
IQIncreaser restoredAndIncreased = (IQIncreaser) ois.readObject();
// Here I am increasing the IQ by one everytime the main runs
restoredAndIncreased.setIq(restoredAndIncreased.getIq()+1);
bakra.setIq(restoredAndIncreased.getIq()+1);
System.out.println("The increased IQ is " + restoredAndIncreased.getIq());
ois.close();
} catch (Exception e) {
e.printStackTrace();
}
You initially run the writeObject() function and everytime it saves 80 as the value. But when you increment the value from the latter part of the code you don't write it to the file. Just increment, read and ignore.
Event though you write it there it will again replace to 80 because of following code in upper part of main method.
try {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:/saveIQ.ser"));
oos.writeObject(bakra);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
Solution
You have to initially set the value 80 and save it to file.
Then when ever you run the program just increment the value and save it again. Don't initialize it into 80 again.
public static void main(String[] args) {
IQIncreaser bakra = new IQIncreaser();
bakra.setIq(80);
try {
if (!Paths.get("D:/saveIQ.ser").toFile().exists()) {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("/tmp/abc.ser"));
oos.writeObject(bakra);
oos.close();
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Welcome to the IQ increaser!!!");
System.out.println("Whenver you run this game your IQ will increase by 1!!");
System.out.println("Just check it out");
System.out.println("Your IQ at beginning was " + bakra.getIq() + ", come back for more");
try {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("D:/saveIQ.ser"));
IQIncreaser restoredAndIncreased = (IQIncreaser) ois.readObject();
// Here I am increasing the IQ by one everytime the main runs
restoredAndIncreased.setIq(restoredAndIncreased.getIq() + 1);
System.out.println("The increased IQ is " + restoredAndIncreased.getIq());
ois.close();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:/saveIQ.ser"));
oos.writeObject(restoredAndIncreased);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}

Android: File not found exception, it worked in the first time?

I am performing a project, where so far in the discipline, we can not use database to persist the data. I am persisting the data in .tmp files. The first time I persisted the list of doctors, and it worked, but now that I'm trying to persist the patient user data, but this error happens, that file is not found.
These are my load, anda save methods in the class "SharedResources":
public void loadUserPatient(Context context) {
FileInputStream fis1;
try {
fis1 = context.openFileInput("patient.tmp");
ObjectInputStream ois = new
ObjectInputStream(fis1);
userPatient = (UserPatient) ois.readObject();
ois.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
} catch(ClassNotFoundException e) {
e.printStackTrace();
}
}
public void saveUserPatient(Context context) {
FileOutputStream fos1;
try {
fos1 = context.openFileOutput("patient.tmp",
Context.MODE_PRIVATE);
ObjectOutputStream oos =
new ObjectOutputStream(fos1);
oos.writeObject(userPatient);
oos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
here is the whole class: https://ideone.com/f3c74u
the error is happening on line 16 of MainActivity:
SharedResources.getInstance().loadUserPatient(this);
here is the whole class "Main": https://ideone.com/OyiljP
And I think this error is ocurring because of the 52nd line of the UserPatientAdd class:
SharedResources.getInstance().getUserPatient();
because when I work with an ArrayList, I put an add at the end of the line, like:SharedResources.getInstance().getDoctors().add(doctor);
And I get confused on how to proceed when I deal only with a user.
This is the whole UserPatientAdd class: https://ideone.com/clUSa3
How can I solve this problem?
You need to set the UserPatient using something like this
In your SharedResources class, create a new method:
public void setUserPatient(UserPatient user) {
userPatient = user;
}
Then in your UserPatientAdd class set the new object:
UserPatient userPatient = new UserPatient (birth, name, bloodType, bloodPressure, cbpm, vacinesTaken, vacinesToBeTaken,
allergies,weight, height, surgeries, desease);
SharedResources.getInstance().setUserPatient(userPatient);
Done

Reading objects from a file ClassCastException error

I am trying to write an ArrayList of Question objects called questions to a file, then reading the file.
My problem is that when I am reading the file, it gives me an error that says: java.lang.ClassCastException: java.lang.String cannot be cast to Question at Quiz.load
My question is, why is this problem occurring and how can I fix it? I've been reading a lot of tutorials and they just cast the object to the class name which is what I did. I included my save & load functions.
Inside Quiz class:
Write Objects To File
ArrayList<Question> questions = new ArrayList<>();
//filename given by user
FileOutputStream fos = new FileOutputStream(filename);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(questions);
Read Objects From File
ArrayList<Question> readQuestions = new ArrayList<>();
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.print("QUIZ LOADING...");
readQuestions.add((Question)ois.readObject()); //problem occurs
Imagine that you have an empty box. You put an apple into the box.
Then you close it, and open it later on. Now, do you think it would work out to expect to find a hamburger in that box?
But that is what you are doing - storing a String and expecting to find a Question object. And that class cast exceptional is how the jvm tells you about reality not fitting your assumptions.
Solution: either store question objects - or expect strings to come back when reading the file.
You are serializing a list and deserializing it with Question.
Just change
readQuestions.add((Question) ois.readObject()); //problem occurs
with this
readQuestions = (ArrayList<Question>) ois.readObject();
Further explanation :
When i tried the example i got this error :
java.lang.ClassCastException: java.util.ArrayList cannot be cast to Question
So most likely if you are getting ClassCastException with String, you are also missing Serializable interface on Question. Something like this :
class Question implements Serializable {
String text;
public Question(String text) {
this.text = text;
}
}
Adding working code :
import java.io.*;
import java.util.ArrayList;
public class ObjectIS {
public static void main(String[] args) {
new ObjectIS().save();
new ObjectIS().load("abcd");
}
public void save() {
try {
ArrayList<Question> questions = new ArrayList<>();
questions.add(new Question("what is your name"));
//filename given by user
FileOutputStream fos = new FileOutputStream("abcd");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(questions);
oos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public void load(String filename) {
try {
ArrayList<Question> readQuestions = new ArrayList<>();
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.print("QUIZ LOADING...");
// readQuestions.add((Question) ois.readObject()); //problem occurs
readQuestions = (ArrayList<Question>) ois.readObject();
System.out.println("ois = " + readQuestions);
ois.close();
fis.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassCastException e) {
e.printStackTrace();
} catch (ClassNotFoundException ex) {
ex.printStackTrace();
}
}
}
class Question implements Serializable {
String text;
public Question(String text) {
this.text = text;
}
#Override
public String toString() {
final StringBuffer sb = new StringBuffer("Question{");
sb.append("text='").append(text).append('\'');
sb.append('}');
return sb.toString();
}
}
It is exactly as I said. You are serialising a String:
oos.writeObject(questions.toString());
And then attempting to deserialize it as a Question, which it never was:
(Question)in.readObject();
Solution:
remove the .toString() part.
deserialize as a List<Question>, which is what it really will be.

Java Serialization

I'm learning now how to do serialization using Java Language. I have read some posts and docs about the subject and I tried to do a simple example (below)
public class SterializeObject implements java.io.Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private transient int code;
public SterializeObject (String n, int c){
name = n;
code = c;
}
public void printAtributes (){
System.out.println("name: " + name + "; code: " + code);
}
}
public class MainClass {
public static void main(String[] agrs) {
SterializeObject ob1 = new SterializeObject("ana", 1);
SterializeObject ob2 = new SterializeObject("rita", 2);
try {
FileOutputStream fileOut = new FileOutputStream("file.data");
ObjectOutputStream outObj = new ObjectOutputStream(fileOut);
outObj.writeObject(ob1);
outObj.writeObject(ob2);
outObj.close();
System.out.println("Objects were serialized!");
} catch (IOException e) {
e.printStackTrace();
}
ArrayList<SterializeObject> list = new ArrayList<SterializeObject>();
try {
FileInputStream fileInput = new FileInputStream("file.data");
ObjectInputStream inputObj = new ObjectInputStream(fileInput);
Object o;
try {
while ((o = inputObj.readObject()) != null) {
list.add((SterializeObject) o);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Erro foi aqui! (1)");
}
inputObj.close();
fileInput.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Erro foi aqui! (2)");
}
for (int i = 0; i < list.size(); ++i) {
list.get(i).printAtributes();
}
}
}
I created a Class SterializeObject that implements java.io.Serializable with two variables: one string (name) and one int (code) that is transient. Then In the main I generate two instances of that class and I tried to write it in a file, that I have done successfully! After that, I try to read the two object with a Loop.. there is my problem.. since the ObjectInputStream dosen't have some kind of method to see if we are in the end or not. So, I tried to do with this condition: (o = inputObj.readObject()) != null.
My output is this:
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 MainClass.main(MainClass.java:30)
Objects were serialized!
Erro foi aqui! (2)
name: ana; code: 0
name: rita; code: 0
I get the objects, but I get an error because, I think, is trying to access to something that doesn't exist.
Someone can tell me other way to do it?
Best Regards.
Read as many objects as the number of written objects, or write the list of objects itself, instead of writing every object one after the other.
(Or rely on the EOFException to detect the end of the stream, but this is ugly).
As many of you told me to do, I created a ArrayList and serialized the ArrayList.
My code is:
public class MainClass {
public static void main(String[] agrs) {
SterializeObject ob1 = new SterializeObject("ana", 1);
SterializeObject ob2 = new SterializeObject("rita", 2);
ArrayList <SterializeObject> list = new ArrayList<>();
list.add(ob1);
list.add(ob2);
ArrayList <SterializeObject> input = new ArrayList<SterializeObject>();
try {
FileOutputStream fileOut = new FileOutputStream("file.data");
ObjectOutputStream outObj = new ObjectOutputStream(fileOut);
outObj.writeObject(list);
outObj.close();
System.out.println("Objects were serialized!");
} catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream fileInput = new FileInputStream("file.data");
ObjectInputStream inputObj = new ObjectInputStream(fileInput);
Object o;
try {
input = (ArrayList<SterializeObject>) inputObj.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Erro foi aqui! (1)");
}
inputObj.close();
fileInput.close();
} catch (IOException e) {
e.printStackTrace();
System.out.println("Erro foi aqui! (2)");
}
for (int i = 0; i < input.size(); ++i) {
input.get(i).printAtributes();
}
}
}
And the output is:
Objects were serialized!
name: ana; code: 0
name: rita; code: 0
Thank you for the help!
Close the FileOutputStream also along with ObjectOutputStream
fileOut.close();
Why don't you add both object to an ArrayList, and serialize the ArrayList. Then you just have to Deserialize the ArrayList and it will be populated with both objects.
You can do this by placing the readObject call inside a try-catch block and catching that EOFException you get, signaling you have read all the objects.
Replace your while loop with this piece of code
do{
try
{
o = inputObj.readObject();
list.add((SterializeObject) o);
}
catch(EOFException e)
{
o = null;
}
}while (o != null);

Categories

Resources