Read the comments for more info on how this works/how to use it.
/*
* Savable.java
*
* Created on March 29, 2004, 11:43 AM
*/
package bot.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
/**
* Any class that implements this can easily be saved and loaded. Basically, you can
* call <PRE>this.save(filename)</PRE> and it will be saved to that file, or
* <PRE>MyClass c = MyClass.load(filename)</PRE> to load it.
* <P>
* Note that every instance variable in the class must be either a primitive type or
* a class that implements Serializable, otherwise, I'm told, something will blow up.
*
* @author iago
*/
abstract public class Savable implements Serializable
{
/** The class saves itself to the specified filename.
* @param filename The file object to save the object as.
* @throws IOException If there is a problem saving the file.
*/
public void save(File filename) throws IOException
{
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(filename));
out.writeObject(this);
out.close();
}
/** The class saves itself using a String for a filename rather than using a File object.
* @param filename The path/name to save the file to.
* @throws IOException If there is a problem saving the file.
*/
public void save(String filename) throws IOException
{
save(new File(filename));
}
/**
* Load and return an instance of the object. If there's an error during the load,
* an exception is thrown.
* @param filename The file object representing the file to load.
* @return An instance of the object, loaded from the file.
* @throws IOException if the file isn't found or if the file is an invalid format.
*/
public static Savable load(File filename) throws IOException
{
try
{
ObjectInputStream in = new ObjectInputStream(new FileInputStream(filename));
Savable ret = (Savable) in.readObject();
in.close();
return ret;
}
catch(ClassNotFoundException e)
{
throw new IOException("Unable to read the file: " + e.toString());
}
}
/**
* Load and return an instance of the object. If there's an error during the load,
* an exception is thrown.
* @param filename A String object representing the full or relative path to the file.
* @return An instance of the object, loaded from the file.
* @throws IOException if the file isn't found or if the file is an invalid format.
*/
public static Savable load(String filename) throws IOException
{
return load(new File(filename));
}
}
Why is this better than Serializable?
Quote from: St0rm.iD on April 14, 2004, 02:07 PM
Why is this better than Serializable?
It uses serializable. It just saves the effort of creating the ObjectOutputStream/ObjectInputStream and creating the File object.
Quote from: St0rm.iD on April 14, 2004, 02:07 PM
Why is this better than Serializable?
indeed, in fact I would say that Serializable is better. No offense, iago, but here's the problem...
Say you have abstract class Car already made in a library. You want to derive class HondaAccord as well as make it Savable; however, you can't do that, because Java doesn't support double inheritence. You can have a ton of interfaces (such as Serializable) on a class, but you can't have:
package MyndFyre.Vehicles;
import Generics.Car;
public class HondaAccord extends Car, Savable
{
//...
}
but you can have:
package MyndFyre.Vehicles;
import Generics.Car;
public class HondaAccord extends Car implements Serializable
{
//...
}
If you need to extend something else, then your superclass can (probably) extends Savable. If not, then just use serializable and write the extra code.
I found myself writing the same code over and over to do the same thing: save a serializable. Mainly classes that I was using to store preferences, which wouldn't extend anything to begin with. So I wrote a class to extend to save me time, and it has.
So my point is, Savable can save you a little time, but if not go ahead and use Serializable :P
import java.io.*;
public class Saver {
public static void save(String filename, Serializable o) throws IOException {
new ObjectOutputStream(new FileOutputStream(filename)).writeObject(o);
}
}
Quote from: St0rm.iD on April 15, 2004, 05:49 PM
import java.io.*;
public class Saver {
public static void save(String filename, Serializable o) throws IOException {
new ObjectOutputStream(new FileOutputStream(filename)).writeObject(o);
}
}
Ugh@* imports, clarity is more important than time.
That doesn't take care of loading.
Doesn't close the file (good coding practice).
I considered doing a static class before, but I found mine much more convenient for what I need.
I'll bet you a cent that it does close the file.
It's better to close the file explicitly.
But, how does it know to? There's no destructors in Java.
Quote from: iago on April 15, 2004, 07:13 PM
It's better to close the file explicitly.
But, how does it know to? There's no destructors in Java.
OK iago, here:
// just for you, even though * syntax doesn't do anything bad...
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class IOer {
public static void save(String filename, Serializable o) throws IOException
{
FileOutputStream fos = new FileOutputStream(filename);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(o);
oos.close();
fos.close();
}
public static Object load(String filename) throws IOException
{
FileInputStream fos = new FileInputStream(filename);
ObjectInputStream oos = new ObjectInputStream(fos);
Object o = oos.readObject();
oos.close();
fos.close();
return o;
}
}
You're right, * imports don't hurt anything programatically, but it clarifies code. If I see a class I don't know, say, for instance, file, I can look at the imports and know to look up "java.io.file".
As for the rest of it, a static class would be ok too, but it doesn't matter :)