Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Top Posters

Who's Online (2)

Powered by Vanilla. Made with Bootstrap.
[Java] Persisting Objects
  • Deque
    Posts: 78
    Persisting Objects

    This tutorial shows you three approaches to persist objects in Java without using a database. Persistence means you save the objects in way that they outlive the program that created them.

    At first you should know how to do a simple FileIO with Strings. This is a correct way:

    [spoiler]
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.DataInputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;

    public class FileIO {

    public static void main(String[] args) {
    writeFile(\"test.txt\");
    readFile(\"test.txt\");
    }

    /**
    * reads a given textfile and prints it out
    *
    * @param filename
    */
    public static void readFile(String filename) {
    FileInputStream fin = null;
    DataInputStream din = null;
    try {
    fin = new FileInputStream(filename);
    din = new DataInputStream(fin);
    BufferedReader reader = new BufferedReader(new InputStreamReader(
    din));
    String line;

    while ((line = reader.readLine()) != null) { // read line by line
    System.out.println(line); // print the content
    }
    } catch (FileNotFoundException e) {
    System.err.println(\"File \" + filename + \" not found\");
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (fin != null) {
    fin.close();
    }
    if (din != null) {
    din.close(); // always close your streams within finally
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    /**
    * writes \"Hello World\" into a textfile
    *
    * @param filename
    */
    public static void writeFile(String filename) {
    FileWriter writer = null;
    BufferedWriter out = null;
    try {
    writer = new FileWriter(filename);
    out = new BufferedWriter(writer);
    out.write(\"Hello World\");
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (out != null) {
    out.close();
    }
    if (writer != null) {
    writer.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    [/spoiler]

    This code writes Hello World into a textfile named "test.txt" and afterwards reads the file and prints its content on your console. Please make sure to close your streams correctly. There are so many wrong samples you will find with google. Streams have to be closed within finally to make sure it is also done after an exception occured. It is ugly to have another try-catch nested in the finally clause, but necessary.

    Now you want to save an object in a file. This object may look like this:


    public class Person {

    private String name;
    private int age;

    public Person(String name, int age) {
    this.name = name;
    this.age = age;
    }

    public void setName(String name) {
    this.name = name;
    }
    public String getName() {
    return name;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public int getAge() {
    return age;
    }
    }



    1. Customize the common file writing methods


    Your first approach may be to write a textfile like this:
    name:Peter
    age:12


    You have to change the above FileIO methods for doing this.

    Get a system independend newline at first, because "\n" won't work on every system:

    public static String newline = System.getProperty(\"line.separator\");


    Change writeFile line 64 to this:

    out.write(\"name:\" + person.getName() + newline + \"age:\"
    + person.getAge());


    Reading is more complicated. We have to identify the attributes by their names ("name" and "age") and afterwards get the value after ":". The method split(":") returns an array with the Strings which are splitted by ":".

    String name = null; //initialize variables for the Person attributes
    Integer age = null;
    try {
    fin = new FileInputStream(filename);
    din = new DataInputStream(fin);
    BufferedReader reader = new BufferedReader(new InputStreamReader(din));
    String line;
    while ((line = reader.readLine()) != null) {
    String[] attributes = line.split(\":\"); //split the line
    if(attributes != null && attributes.length == 2){ //make sure not to go over bounds
    //there may be an empty line
    if(attributes[0].equals(\"name\")){ //get name attribute
    name = attributes[1];
    }
    if(attributes[0].equals(\"age\")){ //get age attribute
    age = Integer.parseInt(attributes[1]);
    }
    }
    }
    return new Person(name, age); //return the new person object


    Here is the whole code again:

    [spoiler]
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.DataInputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStreamReader;

    public class FileIO {

    public static String newline = System.getProperty(\"line.separator\");

    public static void main(String[] args) {
    Person peter = new Person(\"Peter\", 12);
    writeFile(\"peter.txt\", peter);
    Person readPerson = readFile(\"peter.txt\");
    System.out.println(\"Persons name: \" + readPerson.getName());
    System.out.println(\"Persons age: \" + readPerson.getAge());
    }

    /**
    * reads a given textfile and prints it out
    *
    * @param filename
    */
    public static Person readFile(String filename) {
    FileInputStream fin = null;
    DataInputStream din = null;
    String name = null;
    Integer age = null;
    try {
    fin = new FileInputStream(filename);
    din = new DataInputStream(fin);
    BufferedReader reader = new BufferedReader(new InputStreamReader(
    din));
    String line;
    while ((line = reader.readLine()) != null) {
    String[] attributes = line.split(\":\");
    if(attributes != null && attributes.length == 2){
    if(attributes[0].equals(\"name\")){
    name = attributes[1];
    }
    if(attributes[0].equals(\"age\")){
    age = Integer.parseInt(attributes[1]);
    }
    }
    }
    return new Person(name, age);
    } catch (FileNotFoundException e) {
    System.err.println(\"File \" + filename + \" not found\");
    } catch (IOException e) {
    e.printStackTrace();
    } catch (NumberFormatException e){
    System.err.println(\"Value after age was no number\");
    } finally {
    try {
    if (fin != null) {
    fin.close();
    }
    if (din != null) {
    din.close(); // always close your streams within finally
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    return null;
    }

    /**
    * writes \"Hello World\" into a textfile
    *
    * @param filename
    */
    public static void writeFile(String filename, Person person) {
    FileWriter writer = null;
    BufferedWriter out = null;
    try {
    writer = new FileWriter(filename);
    out = new BufferedWriter(writer);
    out.write(\"name:\" + person.getName() + newline + \"age:\"
    + person.getAge());
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (out != null) {
    out.close();
    }
    if (writer != null) {
    writer.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }
    }
    [/spoiler]

    Now imagine you want to persist more Objects. You have to code new methods to do this for every Object you want to persist. You also have to change your methods if you extend or change the Person class. This is a pain in the ass.
    But there is a simpler approach.

    2. Use ObjectStreams

    At first implement the Serializable Interface for Person:

    public class Person implements Serializable {


    Now look at those methods:

    [spoiler]
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.DataInputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;

    public class FileIO {

    public static String newline = System.getProperty(\"line.separator\");

    public static void main(String[] args) {
    Person peter = new Person(\"Peter\", 12);
    writeFileByObjectStream(\"peter.txt\", peter);
    Object obj = readFileByObjectStream(\"peter.txt\");
    if (obj instanceof Person) { //do a save typecast
    Person person = (Person) obj;
    System.out.println(\"Persons name: \" + person.getName());
    System.out.println(\"Persons age: \" + person.getAge());
    }
    }

    public static void writeFileByObjectStream(String filename, Object object) {
    ObjectOutputStream oos = null;
    FileOutputStream fos = null;
    try {
    fos = new FileOutputStream(filename);
    oos = new ObjectOutputStream(fos);

    oos.writeObject(object);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (oos != null) {
    oos.close();
    }
    if (fos != null) {
    fos.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    public static Object readFileByObjectStream(String filename) {
    Object obj = null;
    ObjectInput in = null;
    InputStream fis = null;
    try {
    fis = new FileInputStream(filename);
    in = new ObjectInputStream(fis);
    obj = in.readObject();

    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } finally {
    try {
    if (in != null) {
    in.close();
    }
    if (fis != null) {
    fis.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    return obj;
    }
    }
    [/spoiler]

    It doesn't matter anymore what kind of object it is. You can read or write anything you want, just implement Serializable. There is just one big disadvantage. This solution is only suitable for temporary files. If you make a program and save important files like this which are not temporary and you change your program sometime later and compile it again, it possibly won't work with the old files.

    What now?

    3. Use XML

    A nice and easy way to do this is using xstream. This is a library you have to download and add xstream.jar and xpp-min.jar to your project first. You find it here: http://xstream.codehaus.org/

    Our code:
    [spoiler]
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.DataInputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;

    import com.thoughtworks.xstream.XStream;

    public class FileIO {

    public static String newline = System.getProperty(\"line.separator\");

    public static void main(String[] args) {
    Person peter = new Person(\"Peter\", 12);
    writeXML(\"peter.txt\", peter);
    Object obj = readXML(\"peter.txt\");
    if (obj instanceof Person) {
    Person person = (Person) obj;
    System.out.println(\"Persons name: \" + person.getName());
    System.out.println(\"Persons age: \" + person.getAge());
    }
    }

    public static void writeXML(String filename, Object object) {
    XStream xstream = new XStream();
    FileWriter writer = null;

    try {
    writer = new FileWriter(filename);
    xstream.toXML(object, writer);

    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (writer != null) {
    writer.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    public static Object readXML(String filename) {
    FileReader reader = null;
    Object obj = null;

    try {
    reader = new FileReader(filename);
    XStream xstream = new XStream();
    obj = xstream.fromXML(reader);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } finally {
    try {
    if (reader != null) {
    reader.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    return obj;
    }
    }
    [/spoiler]

    This is in my opinion the best solution for saving objects in non-temporary files.

    Here is the whole code with all methods from today to persist objects:
    [spoiler]
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.DataInputStream;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.ObjectInput;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;

    import com.thoughtworks.xstream.XStream;

    public class FileIO {

    public static String newline = System.getProperty(\"line.separator\");

    public static void main(String[] args) {
    Person peter = new Person(\"Peter\", 12);
    writeXML(\"peter.txt\", peter);
    Object obj = readXML(\"peter.txt\");
    if (obj instanceof Person) {
    Person person = (Person) obj;
    System.out.println(\"Persons name: \" + person.getName());
    System.out.println(\"Persons age: \" + person.getAge());
    }
    }

    public static void writeXML(String filename, Object object) {
    XStream xstream = new XStream();
    FileWriter writer = null;

    try {
    writer = new FileWriter(filename);
    xstream.toXML(object, writer);

    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (writer != null) {
    writer.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    public static Object readXML(String filename) {
    FileReader reader = null;
    Object obj = null;

    try {
    reader = new FileReader(filename);
    XStream xstream = new XStream();
    obj = xstream.fromXML(reader);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } finally {
    try {
    if (reader != null) {
    reader.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }

    return obj;
    }

    public static Person readFile(String filename) {
    FileInputStream fin = null;
    DataInputStream din = null;
    String name = null;
    Integer age = null;
    try {
    fin = new FileInputStream(filename);
    din = new DataInputStream(fin);
    BufferedReader reader = new BufferedReader(new InputStreamReader(
    din));
    String line;
    while ((line = reader.readLine()) != null) {
    String[] attributes = line.split(\":\");
    if (attributes != null && attributes.length == 2) {
    if (attributes[0].equals(\"name\")) {
    name = attributes[1];
    }
    if (attributes[0].equals(\"age\")) {
    age = Integer.parseInt(attributes[1]);
    }
    }
    }
    return new Person(name, age);
    } catch (FileNotFoundException e) {
    System.err.println(\"File \" + filename + \" not found\");
    } catch (IOException e) {
    e.printStackTrace();
    } catch (NumberFormatException e) {
    System.err.println(\"Value after age was no number\");
    } finally {
    try {
    if (fin != null) {
    fin.close();
    }
    if (din != null) {
    din.close(); // always close your streams within finally
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    return null;
    }

    public static void writeFile(String filename, Person person) {
    FileWriter writer = null;
    BufferedWriter out = null;
    try {
    writer = new FileWriter(filename);
    out = new BufferedWriter(writer);
    out.write(\"name:\" + person.getName() + newline + \"age:\"
    + person.getAge());
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (out != null) {
    out.close();
    }
    if (writer != null) {
    writer.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    public static void writeFileByObjectStream(String filename, Object object) {
    ObjectOutputStream oos = null;
    FileOutputStream fos = null;
    try {
    fos = new FileOutputStream(filename);
    oos = new ObjectOutputStream(fos);

    oos.writeObject(object);
    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } finally {
    try {
    if (oos != null) {
    oos.close();
    }
    if (fos != null) {
    fos.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    }

    public static Object readFileByObjectStream(String filename) {
    Object obj = null;
    ObjectInput in = null;
    InputStream fis = null;
    try {
    fis = new FileInputStream(filename);
    in = new ObjectInputStream(fis);
    obj = in.readObject();

    } catch (FileNotFoundException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    } catch (ClassNotFoundException e) {
    e.printStackTrace();
    } finally {
    try {
    if (in != null) {
    in.close();
    }
    if (fis != null) {
    fis.close();
    }
    } catch (IOException e) {
    e.printStackTrace();
    }
    }
    return obj;
    }
    }
    [/spoiler]

    I wish you success with coding.

    Deque
  • peann
    Posts: 14
    You can use embedded databases with Java now - Check out Apache Derby. I created a language-learning application for college using it 2 years back. It's very powerful. Good post though :)
  • Deque
    Posts: 78
    Thanks for this information. This guide was not designed to explain how to work with databases. But I keep it in mind in case I need it elsewhere.
  • Xin
    Posts: 3,251
    Great tutorial, its nice to have a good java coder submitting content
    Xin