Как я могу сохранить ArrayList‹MyObject› в файл?

Как сохранить список ArrayList в файл? Что я делаю не так?

Я использовал этот вопрос SO, чтобы помочь мне с сериализуемыми объектами.:

как сериализовать ArrayList на Android

и я использовал этот вопрос SO о том, как написать список массивов:

Java - Как я могу записать свой ArrayList в файл и прочитать (загрузить) этот файл в исходный ArrayList?

Однако, когда я пытаюсь записать в файл, я получаю сообщение об ошибке:

java.io.NotSerializableException: в

java.io.ObjectOutputStream.writeObject в

com.mycompany.MyClass.saveData

Вот MyClass, который пытается сохранить файл

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();
            }
        }
    }

}

Вот MyCustomObject

public class MyCustomObject implements Serializable {

    public String myname = "";
    public String someOtherItem = "";
    public int aNumber = 0;
    public MyCustomObject getCustomObject() {
        return this;
    }
}

person user-44651    schedule 11.11.2016    source источник
comment
Что вы пытаетесь сериализовать — переменную-член arrayList экземпляра MyClass или сам экземпляр MyClass?   -  person clownba0t    schedule 11.11.2016
comment
Думаю, мне следует сериализовать свой ArrayList, так как это то, что нужно сохранить.   -  person user-44651    schedule 11.11.2016
comment
Действительно - MyClass, кажется, имеет член Context (см. this.appContext в методе init), который, конечно, не сериализуем!   -  person clownba0t    schedule 11.11.2016
comment
Поскольку MyCustomObject IS Serializable, не будет ли ArrayList‹MyCustomObject› сериализуемым через наследование? Это буквально список сериализуемых объектов.   -  person user-44651    schedule 11.11.2016
comment
Да, но вы пытаетесь сериализовать экземпляр MyClass, верно? В противном случае вы не увидите com.mycompany.MyClass.saveData в трассировке стека исключений. Простая реализация интерфейса Serializable не делает класс сериализуемым волшебным образом — именно для этого и предназначен NotSerializableException. В опубликованной вами трассировке стека отсутствуют данные, но я ожидаю, что вы получили их, потому что Android пытался сериализовать переменную-член Context для MyClass, которая, как я уже сказал, не сериализуема.   -  person clownba0t    schedule 11.11.2016
comment
Кроме того, вам не нужен специальный код обработки в MyClass для сериализации ArrayList из MyCustomObject экземпляров, потому что ArrayList сам реализует интерфейс Serializable, а рассматриваемый ArrayList содержит MyCustomObject экземпляров, которые также сериализуемы. Взгляните на developer.android.com/reference/java/io/Serializable. html для более подробной информации.   -  person clownba0t    schedule 11.11.2016
comment
Ааа! Хорошо, позвольте мне прочитать это очень быстро.   -  person user-44651    schedule 11.11.2016


Ответы (1)


Замените этот метод

 public MyCustomObject MyCustomObject() {
        return this;
 }

в вашем классе MyCustomObject, и ваш код должен работать нормально. Используйте что-то вроде

 public MyCustomObject getMyCustomObject() {
        return this;
 }

Потому что то, как вы называете свой метод, конфликтует с конструктором по умолчанию, который java создает для класса MyCustomObject, когда вы сами не предоставляете конструктор. Я предполагаю, что вы используете этот метод, чтобы иметь возможность добавить экземпляр MyCustomObject в ваш список массивов: вам действительно не нужен такой метод, но при правильном именовании вы все равно можете его использовать.

Вы также должны поместить образцы данных в свой список ArrayList перед его сохранением на диск, вызвав метод saveData().

Вот иллюстрация из вашего кода, который работает. Я не уверен, что именно представляет собой ваш объект Context, но вы используете его, чтобы получить доступ к пути к файлу, поэтому, чтобы все заработало, я просто использовал определенный путь к файлу.

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();
                }
            }
        }

    }
}

Как видно из кода, при первом запуске метода main файл будет сохранен на диске с массивомList, заполненным одним объектом. Второй запуск считывает из файла, а затем я печатаю количество элементов и информацию, которую я сохранил ранее: рисунок иллюстрирует результат

введите здесь описание изображения

person alainlompo    schedule 11.11.2016
comment
Спасибо. Позвольте мне подумать об этом с вашими предложениями, и я свяжусь с вами - person user-44651; 11.11.2016
comment
@ user-44651 ты пробовал? это работает для вас? - person alainlompo; 11.11.2016
comment
Нет, я все еще получаю java.io.NotSerializableException: W/System.err: at java.io.ObjectOutputStream.writeNewObject при сохранении - person user-44651; 11.11.2016
comment
Затем, когда файл создан, если приложение перезапускается, я получаю Read an exception; java.io.NotSerializableException: W/System.err: at java.io.ObjectInputStream.readNonPrimitiveConten - person user-44651; 11.11.2016
comment
Действительно? Изменили ли вы имя метода MyCustomObject MyCustomObject() в классе MyCustomObject? - person alainlompo; 11.11.2016
comment
Да, я обновил код в своем вопросе, чтобы отразить изменения, внесенные на основе ваших предложений. - person user-44651; 11.11.2016
comment
В файле не всегда будут храниться данные. Иногда файл будет пуст. - person user-44651; 11.11.2016
comment
Да, я обновил свой ответ. Вы помещаете примеры экземпляров MyCustomObject в список перед его сохранением? В вашем посте это не отображается - person alainlompo; 11.11.2016
comment
да, будет экземпляр, в котором в файле ничего не будет, поэтому мне нужно сохранить его только с пустым ArrayList - person user-44651; 11.11.2016
comment
Он все еще работает для меня даже без образцов данных. Можете ли вы поделиться со мной своим фактическим кодом на платформе обмена, если это возможно: я хотел бы взглянуть поближе - person alainlompo; 11.11.2016
comment
Конечно, мы можем перейти в чат? - person user-44651; 11.11.2016
comment
Давайте продолжим обсуждение в чате. - person alainlompo; 11.11.2016