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)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.