Here's my current code:
//export method
public static void exportObj (Object obj, String fname) {
try {
// Serialize data object to a file
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(fname));
out.writeObject(obj);
out.close();
} catch (IOException e) {}
}
//import method
public static Object importObj (String fname) {
try {
ObjectInputStream in = new ObjectInputStream(new FileInputStream(fname));
return in.readObject();
} catch (IOException e) {}
return new Object();
}
The export function works fine, I think, it turns my User object into a file and saves it, but then when I try to import it, it gives me a ClassNotFound Exception. What is happening?
All the classes you want to deserialize must exist on the CLASSPATH of the project that contains the import code.
Related
I'm trying to create a new PrintWriter object within a try with resources block as below, but it's giving me an error saying outFile cannot be resolved to a type:
public class DataSummary {
PrintWriter outFile;
public DataSummary(String filePath) {
// Create new file to print report
try (outFile = new PrintWriter(filePath)) {
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
EDIT:
A reason why I didn't want to declare the PrintWriter object within the try block is because I want to be able to reference the outFile object in other methods of my class.
It seems like I can't do it with try with resources, so I created it within a normal try/catch/finally block.
The text file is being created. However, when I try to write to file in another method, nothing seems to be printing in the text file, test.txt.
Why is this??
public class TestWrite {
PrintWriter outFile;
public TestWrite(String filePath) {
// Create new file to print report
try {
outFile = new PrintWriter(filePath);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
} finally {
outFile.close();
}
}
public void generateReport() {
outFile.print("Hello world");
outFile.close();
}
}
Instead of trying to do everything in a constructor, I will demonstrate the preferred way to use a try-with-resources and invoke another method. Namely, pass the closeable resource to the other method. But I strongly recommend you make the opener of such resources responsible for closing them. Like,
public void writeToFile(String filePath) {
try (PrintWriter outFile = new PrintWriter(filePath)) {
generateReport(outFile);
} catch (FileNotFoundException e) {
System.out.println("File not found");
e.printStackTrace();
}
}
private void generateReport(PrintWriter outFile) {
outFile.print("Hello world");
}
Appended are my little utility functions for serialising objects. I just encountered following problem:
I renamed a package and suddenly I get a java.lang.ClassCastException when opening my app and trying to read serialised data...
Can I somehow solve that? I would like my serialisations to be working after a renaming, can I do something to implement this? Via some versioning for example?
Here are my two simple functions I use currently:
public static String serialize(Object object)
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try
{
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
oos.flush();
oos.close();
} catch (IOException e)
{
L.e(StringUtil.class, e);
}
return Base64.encodeToString(baos.toByteArray(), 0);
}
public static <T> T deserialize(String serializedObject, Class<T> clazz)
{
if (serializedObject == null)
return (T)null;
byte [] data = Base64.decode(serializedObject, 0);
Object o = null;
try
{
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(data));
o = ois.readObject();
ois.close();
}
catch (IOException e)
{
L.e(StringUtil.class, e);
}
catch (ClassNotFoundException e) {
L.e(StringUtil.class, e);
}
return (T)o;
}
I can suggest next options:
add support to your deserialize method to deal with old package names
convert byte [] data to String
replace old package name with new in deserialized data (with regexp)
continue to deserialize with ObjectInputStream
I'm trying to read from a file I have saved using the following code:
public void saveOnFile() {
try {
ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("object.txt"));
output.writeObject(mediaList);
output.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
public void readFromFile() {
try {
ObjectInputStream inStream = new ObjectInputStream(new FileInputStream("object.txt"));
this.mediaList.add( (Media) inStream.readObject());
inStream.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
However, I don't know if ObjectInputStream knows what objects are inputted. Objects in this case can either be a "Movie" or a "TVShow" but the are all subclasses to Media.
I get the following errors:
java.lang.ClassCastException: java.util.ArrayList cannot be cast to project.Media
at project.MediaHandler.readFromFile(MediaHandler.java:66)
at project.Window.<init>(Window.java:73)
at project.Window.main(Window.java:199)
The Object that you wrote to the ObjectOutputStream is called mediaList, therefore I assume that this is an ArrayList<Media> rather than each individual Media object.
On the ObjectInputStream, you are reading an object and casting it to Media, but I think that you will find that it is an ArrayList<Media> (or however mediaList is defined when it is written to the ObjectOutputStream).
I have certain arraylists in my programm which I would like to write into a file so I can read them when starting the programm for a second time.
Currently it works for an arraylist of persons.
The reading part:
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("test.txt"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
team.setPersonList((ArrayList<Person>) ois.readObject());
The writeToFile class:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
public class WriteToFile {
public void write(ArrayList<Person> Data ) throws IOException, ClassNotFoundException{
// create a new file with an ObjectOutputStream
FileOutputStream out = new FileOutputStream("test.txt");
ObjectOutputStream oout = new ObjectOutputStream(out);
// write something in the file
oout.writeObject(Data);
// close the stream
oout.close();
// create an ObjectInputStream for the file we created before
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(new FileInputStream("test.txt"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// read and print what we wrote before
System.out.println("" + ois.readObject());
ois.close();
}
}
In main:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class Main {
public static void main(String[] args) throws ClassNotFoundException, IOException{
BufferedReader scan = new BufferedReader(new InputStreamReader(System.in));
Team team = new Team(scan);
new InlogSystem(team, scan);
ArrayList<Person> playersData = team.getPersonList();
WriteToFile x = new WriteToFile();
x.write(playersData);
scan.close();
}
}
So this is the working part,
Now i want an arraylist of Strings to write into another txt file (not test like the personlist) using the same writeToFile class.
Obviously the writemethod only works for an arraylist of type person, and it always saves the array into "test.txt".
How do I write this arraylist without making a new method and having alot of ambigious code?
Thanks alot!
You can change the parameter type ArrayList<String> to ArrayList<?> or even List<?> or, what I would suggest, to Object. Then, your method is capable of writing arbitrary objects.
Using generics is useless here: It provides compile-time type checking, which wouldn't be used in your method.
By the way, your exception handling is very bad. I suggest you catch and re-throw the ClassNotFoundException as an IOException; FileNotFoundException is just a subclass of IOException and needn't be catched seperately - and why do you catch an IOException at all when your method is declared as throws IOException ?
Amend your method to accept List instead, where T is parametrized object. Refer to generics documentation
Use a generic method and pass the filename as a parameter i.e.
public <T implements Serializable> void write(ArrayList<T> Data, String filename) throws IOException {
// create a new file with an ObjectOutputStream
FileOutputStream out = new FileOutputStream(filename);
ObjectOutputStream oout = new ObjectOutputStream(out);
// write something in the file
oout.writeObject(Data);
// close the stream
oout.close();
// create an ObjectInputStream for the file we created before
ObjectInputStream ois = null;
ois = new ObjectInputStream(new FileInputStream("test.txt"));
// read and print what we wrote before
System.out.println("" + ois.readObject());
ois.close();
}
This is a followup to Serializing a vector
I'm trying to implement loading and saving for a game I'm working on.
I want to save a Maze which contains, among other attributes, an ArrayList of Entity.
Entity is a super class for Dragon, Hero and Item. All three of these types can be contained at once in the vector.
Using the "automatic" serialization mechanism (adding implements Serializable to Maze) saves all attributes but the ArrayList.
Why does this happen?
My code is below, for completeness' sake.
package logic;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public final class LoadAndSave {
public static final transient boolean available = false;
public static final boolean serialize(Object obj) {
// Write to disk with FileOutputStream
FileOutputStream saveFile;
try {
saveFile = new FileOutputStream("game.sav");
} catch (FileNotFoundException e) {
return false;
}
// Write object with ObjectOutputStream
ObjectOutputStream objOut;
try {
objOut = new ObjectOutputStream(saveFile);
} catch (IOException e) {
//
return false;
}
// Write object out to disk
try {
objOut.writeObject(obj);
} catch (IOException e) {
return false;
}
return true;
}
public static final Object load() {
FileInputStream fileIn;
try {
fileIn = new FileInputStream("game.sav");
} catch (FileNotFoundException e1) {
return null;
}
// Read object using ObjectInputStream
ObjectInputStream objIn;
try {
objIn = new ObjectInputStream(fileIn);
} catch (IOException e) {
return null;
}
// Read an object
Object obj;
try {
obj = objIn.readObject();
} catch (IOException e) {
return null;
} catch (ClassNotFoundException e) {
return null;
}
return obj;
}
}
Is Entity serializable too? (you mentioned that just Maze is serializable).
And be sure that the list is not defined as transient or static, otherwise it will be skipped by the serialization mechanism.
I checked Your code with the following assumptions:
class Entity implements Serializable {}
and:
private char[][] mazeWalls = new char[0][0];
private Vector<Entity> entities = new Vector<Entity>();
...and it works perfectly, serializing and deserializing empty Entity objects...
You need to make sure that you close your streams. Your code for load() can be simplified to look something like this:
ObjectInputStream objIn = null;
try {
objIn = new ObjectInputStream(new FileInputStream("game.sav"));
return objIn.readObject();
} catch (Exception exception) {
// Deal with errors
return null;
} finally {
if (objIn != null) {
try {
objIn.close();
} catch (Exception exception) {}
}
}
serialise() can be altered in a similar way.