1

How can I save an ArrayList to a file? What am I doing wrong?

I have used this SO question to help me with Serializable objects.:

how to serialize ArrayList on android

and I used this SO question on how to write an array list:

Java - How Can I Write My ArrayList to a file, and Read (load) that file to the original ArrayList?

However when I attempt to write the to the file I get the error:

java.io.NotSerializableException: at

java.io.ObjectOutputStream.writeObject at

com.mycompany.MyClass.saveData

Here is MyClass that attempts to save the file

private ArrayList < MyCustomObject > arrayList;
private File dataFile;
private String FILE_NAME = "FILE_DATA.dat";

public void init(final Context context) {
    this.appContext = context;

    dataFile = new File(appContext.getFilesDir(), FILE_NAME);

    if (dataFile.exists()) {
        loadData();

    } else {

        try {
            dataFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }

        arrayList = new ArrayList < MyCustomObject > ();
saveData();
   }

}


private void saveData() {
    FileOutputStream fos = null;

    try {
        fos = new FileOutputStream(dataFile);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {

        if (fos != null) {

            ObjectOutputStream oos = null;
            try {

                oos = new ObjectOutputStream(fos);

                if (oos != null) {

                    oos.writeObject(arrayList);

                }
                assert oos != null;
                oos.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


}

private void loadData() {

    FileInputStream fis = null;
    try {
        fis = new FileInputStream(dataFile);
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } finally {

        if (fis != null) {

            ObjectInputStream ois = null;
            try {
                ois = new ObjectInputStream(fis);

                if (ois != null) {

                    try {

                        arrayList = (ArrayList < MyCustomObject > ) ois.readObject();
                    } catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    }
                } else {

                }
                assert ois != null;
                ois.close();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}

Here is MyCustomObject

public class MyCustomObject implements Serializable {

    public String myname = "";
    public String someOtherItem = "";
    public int aNumber = 0;
    public MyCustomObject getCustomObject() {
        return this;
    }
}
Community
  • 1
  • 1
user-44651
  • 3,924
  • 6
  • 41
  • 87
  • What are you trying to serialise - the `arrayList` member variable of a `MyClass` instance, or the `MyClass` instance itself? – clownba0t Nov 11 '16 at 17:20
  • I guess I should be serializing my ArrayList since that is what needs to be saved. – user-44651 Nov 11 '16 at 18:14
  • Indeed - `MyClass` seems to have a `Context` member (see `this.appContext` in the `init` method) which is certainly _not_ serialisable! – clownba0t Nov 11 '16 at 18:16
  • Since MyCustomObject IS Serializable, wouldn't the ArrayList also be Serializable through inheritance? It is literally a list of Serializable objects. – user-44651 Nov 11 '16 at 18:18
  • Yes, but you're trying to serialise an instance of `MyClass`, right? Otherwise, you wouldn't be seeing `com.mycompany.MyClass.saveData` in the exception stack trace. Simply implementing the `Serializable` interface doesn't magically make a class serialisable - this is exactly what the `NotSerializableException` is for. The stack trace you posted is missing data, but I expect you received it because Android was attempting to serialize the `Context` member variable of `MyClass`, which as I said is not serialisable. – clownba0t Nov 11 '16 at 18:30
  • As an aside, you shouldn't need the special handling code in `MyClass` to serialise the `ArrayList` of `MyCustomObject` instances, because `ArrayList` itself implements the `Serializable` interface and the `ArrayList` in question holds `MyCustomObject` instances which are also serialisable. Take a look at https://developer.android.com/reference/java/io/Serializable.html for more details. – clownba0t Nov 11 '16 at 18:31
  • 1
    Ahhh! Ok let me read that real quick. – user-44651 Nov 11 '16 at 18:35

1 Answers1

1

Replace this method

 public MyCustomObject MyCustomObject() {
        return this;
 }

in your MyCustomObject class and your code should work fine. Use something like

 public MyCustomObject getMyCustomObject() {
        return this;
 }

Because the way you name your method is conflicting wit the default constructor that java creates for MyCustomObject class when you do not provide a constructor yourself. I assume that you are using this method to be able to add an instance of MyCustomObject to your array list: you don't really need such a method but with the proper naming you can still use it.

You should also put sample datas in your ArrayList before saving it to the disk by calling the saveData() method.

Here is an illustration from your code that works. I am not sure what your Context object is exactly but your are using it to get access to the file path, so to get things going I just used a particular file path.

public class MyClass {
    private ArrayList < MyCustomObject > arrayList;
    private File dataFile;
    private String FILE_NAME = "FILE_DATA.dat";

    public void init(final Context context) {


        dataFile = new File("C:\\lompo\\file1.txt");

        if (dataFile.exists()) {
            loadData();

        } else {

            try {
                dataFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }

            arrayList = new ArrayList < MyCustomObject > ();
            MyCustomObject obj1 = new MyCustomObject();
            obj1.aNumber = 125;
            obj1.myname = "HIS NAME";
            arrayList.add(obj1);
            saveData();
       }

    }

    public static void main(String[] args) {
        MyClass myClazz = new MyClass();
        myClazz.init(null);

        System.out.println("Arraylist has " + myClazz.arrayList.size() + " elements");
    }

    private void saveData() {
        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(dataFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fos != null) {

                ObjectOutputStream oos = null;
                try {

                    oos = new ObjectOutputStream(fos);

                    if (oos != null) {

                        oos.writeObject(arrayList);

                    }
                    assert oos != null;
                    oos.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }

    private void loadData() {

        FileInputStream fis = null;
        try {
            fis = new FileInputStream(dataFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {

            if (fis != null) {

                ObjectInputStream ois = null;
                try {
                    ois = new ObjectInputStream(fis);

                    if (ois != null) {

                        try {

                            arrayList = (ArrayList < MyCustomObject > ) ois.readObject();
                        } catch (ClassNotFoundException e) {
                            e.printStackTrace();
                        }
                    } else {

                    }
                    assert ois != null;
                    ois.close();

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

As you can see in the code, the first run of the main method will save the file on disk with an arrayList populated by one object. The second run reads from the file and then I printed the number of elements and the infos that I have saved before: the picture illustrates the result

enter image description here

alainlompo
  • 4,414
  • 4
  • 32
  • 41