Исключение необязательных данных false при чтении объекта из файла

Вопрос или проблема

Я пытаюсь прочитать объекты из файла, чтобы отобразить их на jpanel, но мне сложно десериализовать их.

public static void saveFile(Screen screen)
{
    JFileChooser find = new JFileChooser();
    find.setCurrentDirectory(new File(System.getProperty("user.dir")));
    int result = find.showSaveDialog(find);
    if(JFileChooser.APPROVE_OPTION == result)
    {
        File file = find.getSelectedFile();
        try
        {
            FileOutputStream fo = new FileOutputStream(file);
            ObjectOutputStream os = new ObjectOutputStream(fo);
            os.writeInt(screen.getObjects().size());
            ImageIO.write(screen.getBackgroundImage(), "png", os);
            for(Item i : screen.getObjects())
            {
                i.removeImage();
                os.writeObject(i);
            }
            os.close();
            fo.close();
            for(Item i : screen.getObjects())
            {
                i.setImg();
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}
public static Screen loadFile()
{
    JFileChooser find = new JFileChooser();
    find.setCurrentDirectory(new File(System.getProperty("user.dir")));
    int result = find.showOpenDialog(find);
    if(JFileChooser.APPROVE_OPTION == result)
    {
        File file = find.getSelectedFile();
        try
        {
            FileInputStream fi = new FileInputStream(file);
            ObjectInputStream is = new ObjectInputStream(fi);
            int items = is.readInt();
            BufferedImage background = ImageIO.read(is);
            Screen screen = new Screen();
            screen.setBackground(background);
            for(int i = 0; i <= items; i++)
            {
                Item object = (Item) is.readObject();
                object.setImg();
                screen.addObject(object);
            }
            is.close();
            fi.close();
            return screen;
        }
        catch(OptionalDataException e)
        {
            System.out.println(e.eof);
            e.printStackTrace();
            return null;
        }
        catch(Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }
}

Объекты screen и item оба реализуют Serializable, и eof возвращает false с целыми числами после изображения фона. Объекты item все имеют буферизованные изображения, которые я сделал перетаскиваемыми на jpanel. Поскольку буферизованные изображения на самом деле не сериализуемы, я удаляю изображения из объектов, а затем записываю их в файл, после чего снова добавляю их после завершения записи для дальнейшего использования и пытаюсь воссоздать их, когда объект item читается.

Ответ или решение

Ошибка при десереализации: Optional Data Exception false

Десереализация объектов из файла может вызывать различные проблемы, и ошибку OptionalDataException можно считать одной из наиболее распространенных при работе с Java-сериализацией. В вашем случае возникают сложности, которые могут быть связаны с попыткой прочитать данные из потока, не соответствующие ожидаемому формату.

Причина ошибки

Ошибка OptionalDataException указывает на наличие двух важных моментов:

  1. Дополнительные данные в потоке: Когда вы выполняете десереализацию, Java ожидает получить конкретные объекты, однако, если в потоке остаются другие данные (например, изображения или любые не сериализуемые типы), это может привести к возникновению OptionalDataException.

  2. Чтение данных: В вашем коде количество объектов items определяется с помощью is.readInt(), а затем вы пытаетесь прочитать именно items + 1 объектов (включая изображение). Следует обратить внимание на то, что считывание изображений (например, через ImageIO.read(is)) не ведет к уменьшению ожидаемого количества объектов для чтения.

Кодовая оптимизация

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

  1. Исправьте цикл чтения объектов:
    Измените цикл в функции loadFile() так, чтобы он верно имел дело с количеством объектов. Вместо операции i <= items, используйте i < items. Это обеспечит правильное чтение данных.

    for (int i = 0; i < items; i++) {
       Item object = (Item) is.readObject();
       object.setImg();
       screen.addObject(object);
    }
  2. Защита при чтении изображений:
    Предложите решение обработать считывание BufferedImage более внимательно, чтобы избежать потенциальных несоответствий. Вы можете временно сохранять и восстанавливать изображения после десереализации.

Пример улучшенного кода

Вот как может выглядеть исправленный метод loadFile():

public static Screen loadFile() {
    JFileChooser find = new JFileChooser();
    find.setCurrentDirectory(new File(System.getProperty("user.dir")));
    int result = find.showOpenDialog(find);
    if (JFileChooser.APPROVE_OPTION == result) {
        File file = find.getSelectedFile();
        try (FileInputStream fi = new FileInputStream(file);
             ObjectInputStream is = new ObjectInputStream(fi)) {
            int items = is.readInt();
            BufferedImage background = ImageIO.read(is);
            Screen screen = new Screen();
            screen.setBackground(background);
            for (int i = 0; i < items; i++) {
                Item object = (Item) is.readObject();
                object.setImg();
                screen.addObject(object);
            }
            return screen;
        } catch (OptionalDataException e) {
            System.out.println(e.eof);
            e.printStackTrace();
            return null; 
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    return null;
}

Заключение

Ваши попытки устранить проблему с десереализацией в Java касаются важности соблюдения формата данных. Убедитесь, что данные, записываемые в поток, соответствуют тем, которые вы потом ожидаете прочитать. Оптимизируя метод загрузки и правильно управляя количеством объектов, вы сможете избежать OptionalDataException. Не забывайте корректно обрабатывать изображения, чтобы обеспечить успешный процесс сериализации и десереализации объектов вашей программы.

Оцените материал
Добавить комментарий

Капча загружается...