• Welcome to Valhalla Legends Archive.
 

Savable - Handy code

Started by iago, April 14, 2004, 10:10 AM

Previous topic - Next topic

iago

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));
   }
   
}
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Banana fanna fo fanna

Why is this better than Serializable?

iago

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.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


MyndFyre

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
{
//...
}
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

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
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Banana fanna fo fanna


import java.io.*;

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

iago

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.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


Banana fanna fo fanna

I'll bet you a cent that it does close the file.

iago

It's better to close the file explicitly.

But, how does it know to?  There's no destructors in Java.
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*


MyndFyre

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;
}
}
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.

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 :)
This'll make an interesting test for broken AV:
QuoteX5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*