PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Saturday, October 29, 2022

[FIXED] Why are my serialized files 0 bytes? And why is it throwing an EOF error when reading them?

 October 29, 2022     eof, java, serialization     No comments   

Issue

I'm working on a game project and I'm creating a save feature. I'm using serialized files in order to directly save objects and retrieve them later. I only have to save one ArrayList<Direction>, where Direction is a custom enum containing UP, DOWN, LEFT, RIGHT, NULL and RESTART for special contexts.

In my code, I create an ArrayList<Direction> containing every movement the user has done since the beginning of the game, and make a save button that stores that ArrayList in a file. Writing the object in the file seems to be fine, no error is thrown or whatever. When using the load button that retrieves the object from the file, I'm getting an EOF error (error is written below the code).

I have noticed my files are 0 bytes, which makes me wonder if the data is actually written in the file, and that could explain the EOF error. I have tried changing the file extension, flushing the ObjectOutputStream before closing it, changing the file name, but none of these seem to fix the issue. Clearly, I need to understand why my file is 0 bytes (and thus preventing me from retrieving any data) and why I'm getting an EOF error when reading the file.

Here is the used code:

public class LevelSaver {
    public LevelSaver() {
    }

    public void saveLevel(ArrayList<Direction> movesHistory, byte level) throws IOException {
        String fileName = "level" + (level < 10 ? "0" + level : level);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy @ HH-mm-ss");
        String currentTime = LocalDateTime.now().format(formatter);
        fileName += " " + currentTime;
        fileName += ".moves";

        File saveFile = new File("src\\main\\resources\\level\\saves\\" + fileName);

        FileOutputStream fileOutputStream = null;
        ObjectOutputStream objectOutputStream = null;

        try {
            fileOutputStream = new FileOutputStream("src\\main\\resources\\level\\saves" + fileName);
            objectOutputStream = new ObjectOutputStream(fileOutputStream);
            objectOutputStream.writeObject(movesHistory);
            objectOutputStream.flush();
        } catch (IOException exception) {
            exception.printStackTrace();
        }

        saveFile.createNewFile();
    }

    public ArrayList<Direction> getHistory(String fileName) {
        FileInputStream fileInputStream = null;
        ObjectInputStream objectInputStream = null;
        try {
            fileInputStream = new FileInputStream("src\\main\\resources\\level\\saves\\" + fileName);
            objectInputStream = new ObjectInputStream(fileInputStream);
            return (ArrayList<Direction>) objectInputStream.readObject();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (objectInputStream != null) {
                try {
                    objectInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return new ArrayList<>();
    }
}

saveLevel() creates a .mov file containing the ArrayList, and getHistory() returns an ArrayList stored in a file. At least they're supposed to.

Here is what happens when using the F and G keys that respectively save and load the moves history.

case F:
    try {
        levelSaver.saveLevel(movesHistory, currentLevel);
    } catch (IOException e) {
        e.printStackTrace();
    }
    direction = Direction.NULL;
    break;
case G:
    // I'm directly specifying the file and it is intended, the file name is correct
    ArrayList<Direction> res = levelSaver.getHistory("level06 09-04-2021 @ 22-08-57.mov");
    direction = Direction.NULL;
    for (Direction dir : res) {
        System.out.print("applied : " + dir);
        // apply moves applies the given move and changes the displayed map on the screen
        applyMove(dir);
    }
    break;

And here is the error that I get when I use the loading function. The error occurs when creating the ObjectInputStream.

java.io.EOFException
        at java.base/java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2932)
        at java.base/java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:3427)
        at java.base/java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:962)
        at java.base/java.io.ObjectInputStream.<init>(ObjectInputStream.java:405)
        at model.LevelSaver.getHistory(LevelSaver.java:41)
        at view.PlayingMenu$1.handle(PlayingMenu.java:150)
        at view.PlayingMenu$1.handle(PlayingMenu.java:87)
        at javafx.base/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
        at javafx.base/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
        at javafx.base/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at javafx.base/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
        at javafx.base/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
        at javafx.base/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
        at javafx.base/javafx.event.Event.fireEvent(Event.java:198)
        at javafx.graphics/javafx.scene.Scene$KeyHandler.process(Scene.java:4064)
        at javafx.graphics/javafx.scene.Scene.processKeyEvent(Scene.java:2123)
        at javafx.graphics/javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2591)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:217)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:149)
        at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$1(GlassViewEventHandler.java:248)
        at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:412)
        at javafx.graphics/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:247)
        at javafx.graphics/com.sun.glass.ui.View.handleKeyEvent(View.java:547)
        at javafx.graphics/com.sun.glass.ui.View.notifyKey(View.java:971)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
        at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
        at java.base/java.lang.Thread.run(Thread.java:832)

Solution

You don't close either stream.

Use try-with-resources:

    try (FileOutputStream fileOutputStream = new FileOutputStream("src\\main\\resources\\level\\saves" + fileName);
         ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) {
        objectOutputStream.writeObject(movesHistory);
    } catch (IOException exception) {
        exception.printStackTrace();
    }


Answered By - Louis Wasserman
Answer Checked By - Gilberto Lyons (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing