Java: исключение OutOfMemory при попытке чтения объектов из очень большого файла - PullRequest
0 голосов
/ 15 марта 2020

Я сохранил почти 10 000 объектов в файле, используя следующий код:

boolean exists = Tools.getDeviceInfo().exists();
        FileOutputStream fos = new FileOutputStream(Tools.getDeviceInfo(), true);
        ObjectOutputStream oos = exists ?
                new ObjectOutputStream(fos) {
                    protected void writeStreamHeader() throws IOException {
                        reset();
                    }
                }:new ObjectOutputStream(fos);
        oos.writeObject(deviceInfos);

Теперь, когда я пытаюсь прочитать файл, он вызывает исключение OutOfMemory. Как я могу решить это. Ниже приведен код для чтения объектов.

FileInputStream fis = new FileInputStream(Tools.getDeviceInfo());
        ObjectInputStream ois = new ObjectInputStream(fis);
        ArrayList<DeviceInfo> arrayList = new ArrayList<>();
        try {
            arrayList.addAll((ArrayList<DeviceInfo>)ois.readObject());
        } catch (Exception e) {
            e.printStackTrace();
        }
        ois.close();
        return arrayList;

Причина, по которой я хочу прочитать все объекты, заключается в том, что я хочу показать все данные в табличном представлении, поэтому мне нужно добавить все (10 тыс. Строк) в массив и показать это на столе. Есть ли возможность ограничить readObject (), чтобы он мог получить только несколько объектов из очень большого файла. Как я могу улучшить это? Пожалуйста, помогите.

Ответы [ 3 ]

0 голосов
/ 15 марта 2020

Вы как бы напичканы здесь.

Похоже, что вы поместили все объекты в список, а затем сохранили список в файл, используя один вызов writeObject.

Если вы это сделаете, у вас нет никакого другого выбора, кроме как прочитать весь список. Я предполагаю, что вы могли бы реализовать хак (с помощью пользовательских методов чтения объектов или аналогичных), чтобы «прочитать» нежелательные DeviceInfo объекты как null, чтобы сэкономить место. Но это может иметь и обратные стороны.

Одним из решений является сериализация исходного списка путем индивидуальной сериализации элементов. Затем вы можете читать их по одному и игнорировать те, которые вам не нужны. Это неэффективно, но вы должны избегать заполнения кучи объектами, которые в данный момент не нужны.

Лучшим решением было бы использование другого метода сохранения данных:

  • Вы можете использовать СУБД, базу данных SQL или базу данных с плоскими файлами (например, BerkleyDB) и выбрать только те строки, которые хотите отобразить.

  • Вы можете использовать другой формат сериализации, такой как JSON, XML или CSV, который имеет потоковый API. Затем вы транслируете весь файл и создаете только те элементы, которые хотите отобразить.

База данных какого-либо типа предпочтительнее.

0 голосов
/ 15 марта 2020

Чтобы прочитать 10k объектов из файла, попробуйте использовать java .util.scanner

FileInputStream fInputStream = null;
    Scanner scanner = null;
    try {
        fInputStream = new FileInputStream(path);//file path
        scanner = new Scanner(fInputStream, "UTF-8");
         ArrayList<DeviceInfo> arrayList = new ArrayList<>();
        while (scanner.hasNextLine()) {
        DeviceInfo dObj = new DeviceInfo();
        dObj = scanner.nextLine();
        arrayList.addall(dObj);
        }
        // note that Scanner suppresses out of memory exception
        if (scanner.ioException() != null) {
            throw scanner.ioException();
        }
    } finally {
        if (fInputStream != null) {
            fInputStream.close();
        }
        if (scanner != null) {
            scanner.close();
        }
        }

Приведенный выше код поможет обработать строки (по одному объекту в каждой строке) в большом файле. без итераций, без исчерпания доступной памяти.

0 голосов
/ 15 марта 2020

Вы сериализуете и десериализуете всю коллекцию в одном go. Если вы напишите отдельные объекты (а не содержащие ArrayList), вы сможете читать диапазон за раз.

...