Valhalla Legends Forums Archive | Java Programming | Savable - Handy code

AuthorMessageTime
iago
Read the comments for more info on how this works/how to use it.

[code]/*
* 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));
}

}
[/code]
April 14, 2004, 3:10 PM
St0rm.iD
Why is this better than Serializable?
April 14, 2004, 7:07 PM
iago
[quote author=St0rm.iD link=board=34;threadid=6299;start=0#msg55107 date=1081969648]
Why is this better than Serializable?
[/quote]

It uses serializable. It just saves the effort of creating the ObjectOutputStream/ObjectInputStream and creating the File object.
April 14, 2004, 7:31 PM
Myndfyr
[quote author=St0rm.iD link=board=34;threadid=6299;start=0#msg55107 date=1081969648]
Why is this better than Serializable?
[/quote]

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:

[code]
package MyndFyre.Vehicles;

import Generics.Car;

public class HondaAccord extends Car, Savable
{
//...
}
[/code]

but you can have:

[code]
package MyndFyre.Vehicles;

import Generics.Car;

public class HondaAccord extends Car implements Serializable
{
//...
}
[/code]
April 14, 2004, 7:32 PM
iago
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
April 14, 2004, 7:46 PM
St0rm.iD
[code]
import java.io.*;

public class Saver {
public static void save(String filename, Serializable o) throws IOException {
new ObjectOutputStream(new FileOutputStream(filename)).writeObject(o);
}
}
[/code]
April 15, 2004, 10:49 PM
iago
[quote author=St0rm.iD link=board=34;threadid=6299;start=0#msg55326 date=1082069368]
[code]
import java.io.*;

public class Saver {
public static void save(String filename, Serializable o) throws IOException {
new ObjectOutputStream(new FileOutputStream(filename)).writeObject(o);
}
}
[/code]
[/quote]

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.
April 15, 2004, 11:06 PM
St0rm.iD
I'll bet you a cent that it does close the file.
April 15, 2004, 11:37 PM
iago
It's better to close the file explicitly.

But, how does it know to? There's no destructors in Java.
April 16, 2004, 12:13 AM
Myndfyr
[quote author=iago link=board=34;threadid=6299;start=0#msg55348 date=1082074402]
It's better to close the file explicitly.

But, how does it know to? There's no destructors in Java.
[/quote]

OK iago, here:

[code]
// 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;
}
}
[/code]
April 16, 2004, 1:04 AM
iago
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 :)
April 16, 2004, 1:26 AM

Search