i am having a little trouble reading a object from a text file as it preduces the following error;
Exception in thread "main" java.lang.ClassCastException: java.util.ArrayList cannot be cast to stock.control.system.StockItem
which is this line;
StockItem result = (StockItem) ois.readObject();
below is how i save my file;
try { FileOutputStream fout = new FileOutputStream(filename);
ObjectOutputStream oos = new ObjectOutputStream(fout);
oos.writeObject(StockItems); }
catch (java.io.FileNotFoundException error) {
System.out.println("FILE NOT FOUND!");
}
and here is what i have done for far for loading the file back into a object ArrayList;
try {
FileInputStream fis = new FileInputStream(filename);
ObjectInputStream ois = new ObjectInputStream(fis);
System.out.println("LOADING DATA ...");
StockItem result = (StockItem) ois.readObject();
ois.close();
System.out.println(result.getItemID() + ", " + result.getItemDesc()
+ ", " + result.getPrice() + ", " + result.getQuantity() + ", "
+ result.getReOrderLevel()); // used for testing
} catch (java.io.FileNotFoundException error) {
System.out.println("FILE NOT FOUND!");
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(StockArrayList.class.getName()).log(Level.SEVERE, null, ex);
}
if anywhere could educate me so it can be done correctly it would be much appreciated.
The error says that what was written to the file is an ArrayList.
Looks like that StockItems you write is ArrayList<StockItem>. When you read, you get the array list back, so you can't cast it to StockItem. You need to cast it to ArrayList and then iterate over the list and cast each element to StockItem.
Looks like the file does not contain what you think it does. It contains an ArrayList, not a StockItem. Try taking the first element of the arraylist:
StockItem result = (StockItem) ((ArrayList)ois.readObject()).get(0)
and see what type that is.
I just had to assign the output to a array list in a tester class which was then in turn fed into a interface and from within the interface i had to assign it into another array list, this was how i fixed this error.
Related
Is it possible to change the object type of an array list i.e. from an Object ArrayList to a specific object ArrayList. I have tried using a for each. Alternatively is there a way to change the filehandling method such that it can return a specific type depending on which file it reads from without duplicating code?
My Attempt:
ArrayList<Object> librarianList = FileHandling.getLibrarianRecords(fileName);
ArrayList<Librarian> libList = new ArrayList<>();
for (Object addType: librarianList) {
libList.add(addType);
}
getLibrarianRecords code
public static ArrayList<Object> getLibrarianRecords(String filename){
ArrayList<Object> fromFile = new ArrayList<>(); //Array of
// existing librarians
try{
FileInputStream fIS =
new FileInputStream(SYSTEM_PATH + filename);
ObjectInputStream oIS = new ObjectInputStream(fIS);
fromFile = (ArrayList<Object>)oIS.readObject();
} catch (IOException ex){
System.out.println("Failed to read from file " + ex.getMessage());
ex.printStackTrace(); //Catches an IO exception.
} catch (ClassNotFoundException ex){
System.out.println("Error class not found" + ex.getMessage());
ex.printStackTrace(); //Catches a class not found
// exception.
}
return fromFile; //Returns the array list.
}
It is rarely a good idea to read objects from a file like this. That said all you really need to do is to cast the result of oIS.readObject() to an ArrayList<Librarian> instead of carrying it to ArrayList<Object> (as you do now) and then amend the return type of getLibrarianRecords. Oh, and naturally also the type of the local variable fromFile.
public static ArrayList<Librarian> getLibrarianRecords(String filename){
ArrayList<Librarian> fromFile = new ArrayList<>(); //Array of
// existing librarians
try{
FileInputStream fIS =
new FileInputStream(SYSTEM_PATH + filename);
ObjectInputStream oIS = new ObjectInputStream(fIS);
fromFile = (ArrayList<Librarian>)oIS.readObject();
} catch (IOException ex){
System.out.println("Failed to read from file " + ex.getMessage());
ex.printStackTrace(); //Catches an IO exception.
} catch (ClassNotFoundException ex){
System.out.println("Error class not found" + ex.getMessage());
ex.printStackTrace(); //Catches a class not found
// exception.
}
return fromFile; //Returns the array list.
}
There should then be no need to loop over the list to actually do the type conversion on an element by element basis.
Thanks to #user3170251 for suggesting casting
ArrayList<Object> librarianList = FileHandling.getLibrarianRecords(fileName);
ArrayList<Librarian> libList = new ArrayList<>();
for (Object addType: librarianList) {
libList.add((Librarian) addType);
}
For changing the type this does work.
You can use this generic class definition
class ArrayListConverter<T> {
List<T> cast;
public ArrayListConverter(List<T> typeList){
cast = new ArrayList<>();
for (Object addType: typeList) {
cast.add((T)addType);
}
}
public List<T> getList(){
return cast;
}
}
Just do this:
ArrayListConverter<Librarian> conv = new ArrayListConverter<>(libList);
ArrayList<Librarian> libListOg = conv.getList();
How do I deserialize multiple objects from a file? Following is code that I have tried which works fine for one object but not for multiple objects.
public List<Show> populateDataFromFile(String fileName) {
// TODO Auto-generated method stub
Show s = null;
//FileInputStream fileIn=null;
try
{
FileInputStream fileIn=new FileInputStream("C:\\Users\\Admin\\Desktop\\Participant_Workspace\\Q1\\ShowBookingSystem\\ShowDetails.ser");
int i=0;
while((i=fileIn.read())!=-1){
// fileIn = new FileInputStream("C:\\Users\\Admin\\Desktop\\Participant_Workspace\\Q1\\ShowBookingSystem\\ShowDetails.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
s = (Show) in.readObject();
in.close();
fileIn.close();
System.out.println("Name: " + s.getShowName());
System.out.println("Show Time: " + s.getShowTime());
System.out.println("Seats Available: " + s.getSeatsAvailable());
}
}catch(IOException i)
{
i.printStackTrace();
}catch(ClassNotFoundException c)
{
System.out.println("Employee class not found");
c.printStackTrace();
}
return null;
}
I even tried using
while((i=fin.read())!=-1)
but it did not work. What change do I need to make?
Try this way:
Show s = null;
try {
FileInputStream fileIn = new FileInputStream(".....");
ObjectInputStream in = new ObjectInputStream(fileIn);
while (true) {
try {
s = (Show) in.readObject();
} catch (IOException ex) {
break;
} catch (ClassNotFoundException ex) {
Logger.getLogger(Test.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("Name: " + s.getShowName());
System.out.println("Show Time: " + s.getShowTime());
System.out.println("Seats Available: " + s.getSeatsAvailable());
}
in.close();
fileIn.close();
Below is a short working example. You will need to remove the ObjectInputStream in = new ObjectInputStream(fileIn); from outside the while loop as well.
FileInputStream fis = new FileInputStream("...");
ObjectInputStream ois = new ObjectInputStream(fis); //<- Outside the while loop.
try
{
while(true)
{
Student std = (Student)ois.readObject();
System.out.println(std.getName());
System.out.println(std.getAge());
}
}
catch(IOException e)
{
e.printStackTrace(); //This exception will be thrown if the End Of File (EOF) is reached.
//
}
finally
{
fis.close(); //<- Outside the while loop.
ois.close(); //<- Outside the while loop.
}
In this case the solution is:
to put all objects in a list
serialize the list
This way you only have one object to de-serialize: the list. (As a bonus you get your object in a nicely organised (or not!) list).
If you have multiples type of object to serialize, serialize them in a list per class. Each list in a different file.
Trying to write an object to an array and then save to output.data, then read the objects again.
Writing:
private void saveBtnActionPerformed(java.awt.event.ActionEvent evt) {
File outFile;
FileOutputStream fStream;
ObjectOutputStream oStream;
try {
outFile = new File("output.data");
fStream = new FileOutputStream(outFile);
oStream = new ObjectOutputStream(fStream);
oStream.writeObject(arr);
JOptionPane.showMessageDialog(null, "File Written Successfully");
oStream.close();
} catch (IOException e) {
System.out.println("Error: " + e);
}
}
Reading:
private void readBtnActionPerformed(java.awt.event.ActionEvent evt) {
File inFile;
FileInputStream fStream;
ObjectInputStream oStream;
try {
inFile = new File("output.data");
fStream = new FileInputStream(inFile);
oStream = new ObjectInputStream(fStream);
//create an array of assessments
ArrayList <Assessment> xList;
xList = (ArrayList<Assessment>)oStream.readObject();
for (Assessment x:xList) {
JOptionPane.showMessageDialog(null, "Name: " + x.getName() + "Type: " + x.getType() + "Weighting: " + x.getWeighting());
}
oStream.close();
} catch (IOException e) {
System.out.println("Error: " + e);
} catch (ClassNotFoundException ex) {
System.out.println("Error: " + ex);
}
}
The code comppiles just fine, and the file itself saves alright too. But when I try to read the file nothing happens, and NetBeans says
"Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: [Lnetbeansswingexample.Assessment; cannot be cast to java.util.ArrayList"
the line of code giving trouble seems to be
xList = (ArrayList<Assessment>)oStream.readObject();
Any help would be really appreciated, thanks. Sorry if the answers obvious, pretty new to programming.
Based on the exception you got, it looks like oStream.readObject() returns an array of Assessment, not a List. You can convert it to a List:
List <Assessment> xList;
xList = Arrays.asList((Assessment[])oStream.readObject());
or if you must use a java.util.ArrayList :
ArrayList<Assessment> xList;
xList = new ArrayList<> (Arrays.asList((Assessment[])oStream.readObject()));
I have a custom class (constructor below) that I cannot seem to serialize.
public ObjectNode(String name, int crackLevel,ArrayList<ObjectNode> filesOnComputer)
Every time I try to serialize an object of this class from an ArrayList of object nodes I get a Class cast exception. ArrayList cannot be cast to ObjectNode
Code- Global Vars:
ArrayList<ObjectNode>a=new ArrayList<ObjectNode>();
File file = new File("/mnt/sdcard/","cheesepuff.txt");
Relevant Code:
public void serializeFile()
{
a.add(new ObjectNode("Level 1 Waterwall","ww1", 1, 5));
try {
Log.i("AAA","before serialize: "+a.toString());
FileOutputStream fos = new FileOutputStream(file);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(a);
oos.flush();
oos.close();
Log.i("AAA","finished serialize");
}
catch(Exception e) {
Log.i("aaa","Exception during serialization: " + e);
System.exit(0);
}
}
public void deserializeFile()
{
try {
FileInputStream fis = new FileInputStream(file);
ObjectInputStream ois = new ObjectInputStream(fis);
ObjectNode obj=(ObjectNode)ois.readObject();
Log.i("aaa","obj: "+obj.ts());
//a.add((ObjectNode) ois.readObject());
ois.close();
Log.i("aaa","after serialize: " + a);
}
catch(Exception e) {
Log.i("aaa","Exception during deserialization: " +
e);
System.exit(0);
}
}
Is my best option to make everything a string in order to serialize that, and then convert the string back to what I actually need after deserialization?
You are serializing a which is ArrayList<ObjectNode>.
oos.writeObject(a);
When deserializing, you get back exactly that, but you try to store it as ObjectNode
ObjectNode obj=(ObjectNode)ois.readObject();
You should do
ArrayList<ObjectNode> obj = (ArrayList<ObjectNode>)ois.readObject();
UPDATE: Or, as PeterLawrey correctly states,
List<ObjectNode> obj = (List<ObjectNode>) ois.readObject;
(probably then you would have to redefine a as List<ObjectNode>, but that is another good thing to do).
You are writing an ArrayList, this means you must cast it to an ArrayList (or better, a List) when you read it.
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.