I have to implement Object Files for a java project, however I am having trouble when it comes to loading the file (Save is all OK)
public static void loadStudentList() {
boolean endOfFile = false;
try {
// create a FileInputStream object, studentFile
FileInputStream studentFile = new FileInputStream("Students.obf");
// create am ObjectImnputStream object to wrap around studentStream
ObjectInputStream studentStream = new ObjectInputStream(studentFile) ;
// read the first (whole) object with the readObject method
Student tempStudent = (Student) studentStream.readObject();
while (endOfFile != true) {
try {
tempStudent = (Student) studentStream.readObject();
stud1.add(tempStudent);
}
catch(EOFException e) {
endOfFile = true;
}
}
studentStream.close();
//use the fact that the readObject throws an EOFException to check whether the end of eth file has been reached
}
catch(FileNotFoundException e) {
System.out.println("File not found");
}
catch(ClassNotFoundException e) { // thrown by readObject
/* which indicates that the object just read does not correspond to any class
known to the program */
System.out.println("Trying to read an object of an unkonown class");
}
catch(StreamCorruptedException e) { //thrown by constructor
// which indicates that the input stream given to it was not produced by an ObjectOutputStream object
System.out.println("Unreadable File Format");
}
catch(IOException e) {
System.out.println("There was a problem reading the file");
}
}
This is the code I used to load the files. The program will load ONLY the last 2 records in my file. The Idea is that I load all of them to an array list for future use in the program. Also I am not getting any of my catches back. Any help? Thanks :)
You never add to the list the first Student that you read
Student tempStudent = (Student) studentStream.readObject();
while (endOfFile != true)
{
try
{
tempStudent = (Student) studentStream.readObject();
stud1.add(tempStudent);
}
Remove the read before the while, like the code below
while (endOfFile != true)
{
try
{
Student tempStudent = (Student) studentStream.readObject();
stud1.add(tempStudent);
}
I am not sure if this will solve your problem
Why don't you add the objects to an ArrayList<Type> then write/serialize them to file
and then for reading/deserialize it, read the data into one ArrayList<Type>.
Then you could fetch your objects one by one from the ArrayList
This might be an easier trouble free way of doing it.
//Serialize
ArrayList<Student> students = new ArrayList<Student>();
//Add the student objects to the array list
File f = new File("FileName.ser");
ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(f));
objOut.writeObject(students);
//Deserialize
ArrayList<Student> students = new ArrayList<Student>();
ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(new File("FileName.ser")));
students = (ArrayList<String>) objIn.readObject();
Related
I'm trying to add items from the console input and scanner input to arraylists in java.
(To run the program user types Program ID)
The problem is that each time I run the program the contents of the arraylists update to only what has been entered that time. I would like the arraylists to contain all of the inputs that have been entered.
public class User{
private static List<String> listNames = new ArrayList<String>();
private static List<Integer> listIds = new ArrayList<Integer>();
public static void main(String[] args)
{
int tempID = 5000;
if (args.length>0) tempID= Integer.parseInt(args[0]);
System.out.println("Login "+tempID);
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your Name : ");
tempName = scanner.nextLine();
User n = new User();
n.ID= tempID;
n.name = tempName;
listIds.add(n.ID);
listNames.add(n.name);
}
}
}
Does anyone know if this is possible?
Everytime you run the program it is going to initialize a different array. To solve this, you can store your data in a database such as MySQL or Oracle. But a more efficient way to solve this is that to save your ArrayList as an object locally using java.io.ObjectInputStream and java.io.ObjectOutputStream
I wrote the following 2 functions
public static ArrayList<Object> loadArrayList(String filename)
{
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream(filename));
ArrayList<Object> arr = (ArrayList<Object>) ois.readObject();
return arr;
} catch (IOException e) {
e.printStackTrace();
return null;
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public static void saveArrayList(ArrayList<Object> arr, String filename)
{
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream(filename));
oos.writeObject(arr);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Call saveArrayList with the first argument is your ArrayList instance and the second argument the filename. You can then load from your local file system using the loadArrayList method with the argument is your filename.
In your case, just call the saveArrayList method when your user exits the program and call the loadArrayList to get all your elements from the previous inputs to resume the user's progress
Every time you compile your program you create new Arrays. So you need another way of saving your inputs like in a SQL Database or you can run your program infinitely with a loop and ask each time for a new entry and collect it with the scanner like you already did but with that method, you can do nothing with the array entries because your asking for entries never stops.
I am writing a small program that inserts customer details in ArrayList and write it in file.
The problem is with ObjectOutputStream I was able to append data in file with turning FileOutputStream("",true). But when I try to read data with ObjectInputStream it only reads data that was inserted at first instance. But data is being added to file.
Here is the code -
public void insertCustomer() throws IOException
{
Customer1=new customerDetails("1", "Moeen4", "654654", "asdf", "coding", "student", "65464", "3210");
Customer3=new customerDetails("3", "Moeen5", "888888", "asdf", "coding", "student2", "65464", "321022");
Customer4=new customerDetails("4", "Moeen6", "654654", "asdf", "coding", "student", "65464", "7890");
_list=new ArrayList<customerDetails>();
_list.add(Customer1);
_list.add(Customer3);
_list.add(Customer4);
customersList cl=new customersList();
cl.WriteObjectToFile(files._customers, _list);
ArrayList<customerDetails>li=new ArrayList<customerDetails>();
li= (ArrayList) cl.ReadObjectFromFile(files._customers);
for(int i=0;i<li.size();i++)
{ System.out.println(li.size());
System.out.println(li.get(i).Id);
System.out.println(li.get(i).name);
System.out.println(li.get(i).annual_Salary);
System.out.println(li.get(i).Company);
System.out.println(li.get(i).dateOfBirth);
System.out.println(li.get(i).phone_Number);
}
}
public void WriteObjectToFile(String filepath,Object serObj) {
try {
FileOutputStream fileOut = new FileOutputStream(filepath,true);
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(serObj);
objectOut.close();
System.out.println("The Object was succesfully written to a file");
} catch (Exception ex) {
ex.printStackTrace();
}
}
public Object ReadObjectFromFile(String filepath) {
try {
FileInputStream fileIn = new FileInputStream(filepath);
ObjectInputStream objectIn = new ObjectInputStream(fileIn);
Object obj = objectIn.readObject();
objectIn.close();
System.out.println("The Object has been read from the file");
return obj;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
The real problem here is this:
FileOutputStream fileOut = new FileOutputStream(filepath, true);
ObjectOutputStream objectOut = new ObjectOutputStream(fileOut);
objectOut.writeObject(serObj);
You cannot append to an existing serialization like this. If you do get an exception when attempting to read any objects appended to a pre-existing (non-empty) file.
There is a trick / hack that allows you to append objects though; see Appending to an ObjectOutputStream. (The trick involves suppressing the writing of the object stream header. It is most easily done by overriding the method that does this.)
The other approach is to keep the ObjectOutputStream open between writeObject calls. However there are use-cases where that won't be possible.
Note that there is a semantic difference between these two approaches. The best way to explain it is that the first one behaves as if you called reset() each time you write an object; see the javadoc.
Another thing to note about your example is that your reader code only reads one object. If you want to read multiple objects, you need to call readObject in a loop. And that will only work if you have used the trick / hack above to avoid writing a spurious header.
As suggested the code is only reading the first object and you would need to use a loop to read all the objects from multiple writes.
However -
If you change the above code i.e. ReadObjectFromFile to use a loop this will lead to an StreamCorruptedException: invalid type code: AC. The ObjectOutputStream constructor writes a serialization stream header to the OutputStream i.e. the file, when it is closed and reopend using new ObjectOutputStream and new FileOutputStream(filepath, true) a new header will be written at the append point so you will get an exception as the header is only expected once at the beginning of the file
This will need to be handled e.g.
Use the same ObjectOutputStream for the duration
Override java.io.ObjectOutputStream.writeStreamHeader() to account for append to a file
Change the approach and use List<List<Object>> which you could read, add, write to as a whole.
Loop example would throw exception unless ObjectOutputStream approach is changed
public Object ReadObjectFromFile(String filepath) {
List<List<Object>> objects = new ArrayList<>();
FileInputStream fileIn = new FileInputStream(filepath);
ObjectInputStream objectIn = new ObjectInputStream(fileIn);
try {
while (true) {
List<Object> obj = (List<Object>) objectIn.readObject();
// This will throw StreamCorruptedException: invalid type code: AC
objects.add(obj);
System.out.println("The Object has been read from the file");
}
} catch (EOFException ex) {
// ENDS WHEN ALL READ
} finally {
fileIn.close();
objectIn.close();
}
return objects;
}
Sudo code List<List<Object>> approach -
public void readAndWrite() {
List<Object> customer = List.of(new CustomerDetails(...),
new CustomerDetails(...),
new CustomerDetails(...));
List<List<Object>> objects = readFromFile("existing-customer-file.txt");
objects.addAll(customer);
writeObjectToFile(objects);
}
I'm trying to read data from a file containing multiple objects of a class. But I'm getting null pointer exception while adding objects to list. can anyone help?
Here's the code:
//I'm following the same approach, but getting null Pointer exception while
//adding the object to a list. I'll post my code below. Can anyone help?
public class DeserializingMultipleObjects {
/**
* #param args the command line arguments
*/
public static void main(String[] args) throws IOException {
//create few objects of student class and serialize them in a single file
Student st1= new Student(1, "abhishek", 24, 1);
Student st2= new Student(2, "Prashant",23,3);
Student st3= new Student(3,"Gayatri",22,2);
Student st4= new Student(4,"Ankul",23,4);
FileOutputStream fout= null;
FileInputStream fin= null;
ObjectInputStream oin=null;
ObjectOutputStream oout= null;
List <Student> studentList=null;
try{
fout= new FileOutputStream("Student.ser");
oout= new ObjectOutputStream(fout);
oout.writeObject(st1);
oout.writeObject(st2);
oout.writeObject(st3);
oout.writeObject(st4);
//objects have been serialized. Now read them and populate in a list
fin= new FileInputStream("Student.ser");
oin= new ObjectInputStream(fin);
boolean flag=false;
while(!flag){
if(oin.readObject()==null || oin.readObject().equals("")){
flag=true;
}
else{
studentList.add((Student)oin.readObject());
}
}
}
catch (ClassNotFoundException ex) {
Logger.getLogger(DeserializingMultipleObjects.class.getName()).log(Level.SEVERE, null, ex);
} finally{
if(fout !=null) try {
fout.close();
} catch (IOException ex) {
Logger.getLogger(DeserializingMultipleObjects.class.getName()).log(Level.SEVERE, null, ex);
}
if(oout !=null){
oout.close();
}
if(fin !=null){
fin.close();
}
if(oin !=null){
oin.close();
}
for(Student student: studentList){
System.out.println(student.name);
}
}
}
}
You read your object three times per iteration.
while(!flag){
Student st = oin.readObject();
if(st == null){
flag=true;
}
else{
studentList.add(st);
}
}
List <Student> studentList=null; is giving the error. When you reach the part where you want to add to studentList with studentList.add((Student)oin.readObject());, the list is a null pointer because you initialized it as such.
You might want to initialize the list to something else than null, e.g. List<Student> studentList = new ArrayList<Student>();
Several mistakes:
You forgot to close the ObjectOutputStream before starting to read from the file
Every time you call readObject(), you read the next object from the stream, so the following lines:
if(oin.readObject()==null || oin.readObject().equals("")){
flag=true;
}
else{
studentList.add((Student)oin.readObject());
}
read 2 or three objects, instead of reading just one. They should be
Object read = oin.readObject()
if(read == null || read.equals("")){
flag=true;
}
else {
studentList.add((Student) read);
}
But readObject() will never return null, and there's no way it returns an empty string, since you have only written instances of Student in the stream.
Everything would be much easier if you just stored your 4 students in a List<Student> and serilaized this list. Deserializing would simply consist in reading one object (so, no loop necessary): the list of students.
Also, closing the ObjectOutputStream will automatically close the FileOutputStream. Same for the ObjectInputStream. So closing the file streams is unnecessary. For a much cleaner and safer resource handling, you should use try-with-resources.
I am trying to serialize an object array and write it to a file named address.ser and then read back from the file, deserialize the object array and display its attributes. I tried serializing the whole arrayList at once(deserializing it in a single session while reading) and also tried serializing each object of the object array one by one(deserializing it one by one while reading). The problem is, while reading back from the address.ser file I am getting data only of the last object which was written and none other.
Here is the code snippet:
Employee[] a=new Employee[5];
List<Employee> arr=new ArrayList<Employee>();
for(int i=0;i<=4;i++)
{
a[i]=new Employee();
System.out.println("Enter name,age,height,weight,house_no:");
a[i].name=sc.next();
a[i].age=sc.nextInt();
a[i].height=sc.nextDouble();
a[i].weight=sc.nextDouble();
a[i].house_no=sc.nextInt();
arr.add(a[i]);
}
This is the code snippet for writing objects to address.ser:
for(int i=0;i<=4;i++)
{
try
{
fout = new FileOutputStream("e:\\address.ser");
oos = new ObjectOutputStream(fout);
oos.writeObject(a[i]);
//oos.writeChars("\n");
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
oos.close();
fout.close();
}
}
This is the code snippet for reading objects from address.ser:
List<Employee> recordList=new ArrayList<Employee>();
for(int i=0;i<=4;i++)
{
try
{
file = new FileInputStream("e:\\address.ser");
input = new ObjectInputStream (file);
//deserialize the List
Employee readCase=(Employee) input.readObject();
recordList.add(readCase);
System.out.print("Employee "+i+" ");
System.out.print((recordList.get(i).name)+" ");
System.out.print((recordList.get(i).age)+" ");
System.out.print((recordList.get(i).height)+" ");
System.out.print((recordList.get(i).weight)+" ");
System.out.print((recordList.get(i).house_no)+" ");
System.out.println();
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
file.close();
input.close();
}
}
The final output being:
This is the way to do,
public class Test {
public static void main(String[] args) {
Employee employee=new Employee("jhon");
Employee employee2=new Employee("jojo");
Employee employee3=new Employee("albin");
ArrayList<Employee> list=new ArrayList<Employee>();
list.add(employee);
list.add(employee2);
list.add(employee3);
try {
FileOutputStream outputStream=new FileOutputStream("add.ser");
ObjectOutputStream objectOutputStream= new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(list);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
FileInputStream inputStream=new FileInputStream("add.ser");
ObjectInputStream objectInputStream =new ObjectInputStream(inputStream);
ArrayList<Employee> list2=(ArrayList<Employee>) objectInputStream.readObject();
for (Employee employee4 : list2) {
System.out.println(employee4.getName());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
The problem is you are trying to write the object in a wrong way. You are writing each element of the ArrayList in a same file. So what is happening is a new element is replacing the old one. So write the whole List at a time liek
oos.writeObject(yourList);
Corrected Solution
You're overwriting the file for each element you attempt to serialize. Therefore, the last serialized element remains. A file of serialized data has a header, so you must write your data in one shot.
fout = new FileOutputStream("e:\\address.ser");
oos = new ObjectOutputStream(fout);
for(int i=0;i<=4;i++)
{
try
{
oos.writeObject(a[i]);
}catch(Exception e){}
}
However, it's more efficient to serialize the entire list in one shot.
I have created a method in my java assignment to write into a file from a LinkedList (I used serialization) , then I have created another method to read the file into the inkedList. The following is my method's body:
try {
FileInputStream fin = new FileInputStream("c:\\Info.ser");
ObjectInputStream ois = new ObjectInputStream(fin);
Employee e = (Employee) ois.readObject();
linkP.add(e);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
but it doesnt work right. I think this part:
Employee e = (Employee) ois.readObject();
linkP.add(e);
reads only the first object of the file into the linkedlist and ignores other objects. I surrounded it for loop and while loop several times but it causes EOFException. How can I change my method to read all of the file's objects into the LinkedList?
If you used LinkedList for serialization you should expect a LinkedList to deserialize:
linkP= (LinkedList) ois.readObject();
instead of
Employee e = (Employee) ois.readObject();
linkP.add(e);
The easiest way is to include the size of the list as the first thing written to the file. When you read the file, the first thing you retrieve is the size. Then you can read the expected number of objects.
Are you sure that the serialized file contains all of the elements? It looks to me like you might only be serializing one.
Note: Please also add the code where you create the info.ser file, since you may have corrupted the ObjectOutputStream by closing/reopening it for each object.
But to answer your question, the proper way of doing it (without catching exceptions) would be:
#Test
public void testSerializingListByEntries() throws Exception {
List<Serializable> list = new ArrayList<Serializable>();
list.add(new Date());
list.add(new Date());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeInt(list.size()); // Magic
for(Serializable o : list) {
oos.writeObject(o);
}
oos.close();
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
int count = ois.readInt();
List<Object> newList = new ArrayList<Object>();
for(int i = 0; i < count;i++) {
newList.add(ois.readObject());
}
ois.close();
assertEquals(list,newList);
}
Yes, you need to close the streams yourself of course. Omitted for readability.
Would probably need to see how you're writing in the first place but generally:
ObjectInputStream is = null;
try
{
is = new ObjectInputStream(new FileInputStream("c:/Info.ser"));
Object object = null;
while ((object = is.readObject()) != null)
{
linkP.add(object);
}
}
catch(Exception e)
{
//Whatever you need to do
}
finally
{
//Never forget to close your streams or you'll run into memory leaks
try
{
if (is != null)
{
is.close();
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
Also, its probably better practice for you to handle the exceptions individually but I can't really tell what the streams throw so replace the (Exception e) with everything else.
surround Employee e = (Employee) ois.readObject();
linkP.add(e);
with a for loop as you suggested and surround the .readObject call with a try/catc(EOFException)
Just catch EOFException separately inside your reading loop and process it accordingly, i.e. break out of the loop.