Вопрос или проблема
Я пытаюсь прочитать объекты из файла, чтобы отобразить их на 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
указывает на наличие двух важных моментов:
-
Дополнительные данные в потоке: Когда вы выполняете десереализацию, Java ожидает получить конкретные объекты, однако, если в потоке остаются другие данные (например, изображения или любые не сериализуемые типы), это может привести к возникновению
OptionalDataException
. -
Чтение данных: В вашем коде количество объектов
items
определяется с помощьюis.readInt()
, а затем вы пытаетесь прочитать именноitems + 1
объектов (включая изображение). Следует обратить внимание на то, что считывание изображений (например, черезImageIO.read(is)
) не ведет к уменьшению ожидаемого количества объектов для чтения.
Кодовая оптимизация
Чтобы исправить вашу проблему, следует убедиться, что читаемые данные соответствуют формату, записанному в файл. Вот несколько советов для улучшения вашего кода:
-
Исправьте цикл чтения объектов:
Измените цикл в функцииloadFile()
так, чтобы он верно имел дело с количеством объектов. Вместо операцииi <= items
, используйтеi < items
. Это обеспечит правильное чтение данных.for (int i = 0; i < items; i++) { Item object = (Item) is.readObject(); object.setImg(); screen.addObject(object); }
-
Защита при чтении изображений:
Предложите решение обработать считывание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
. Не забывайте корректно обрабатывать изображения, чтобы обеспечить успешный процесс сериализации и десереализации объектов вашей программы.