为什么我的序列化文件是 0 字节?为什么在读取它们时会抛出 EOF 错误?
Why are my serialized files 0 bytes? And why is it throwing an EOF error when reading them?
我正在做一个游戏项目,我正在创建一个保存功能。我正在使用序列化文件,以便直接保存对象并在以后检索它们。我只需要保存一个 ArrayList<Direction>
,其中 Direction
是一个包含 UP
、DOWN
、LEFT
、RIGHT
、[=19 的自定义枚举=] 和 RESTART
用于特殊情况。
在我的代码中,我创建了一个 ArrayList<Direction>
包含用户从游戏开始以来所做的每一个动作,并制作了一个保存按钮,将 ArrayList 存储在一个文件中。在文件中写入对象似乎没问题,没有抛出错误或其他任何错误。使用从文件中检索对象的加载按钮时,出现 EOF 错误(错误写在代码下方)。
我注意到我的文件是 0 字节,这让我想知道数据是否真的写入了文件,这可以解释 EOF 错误。我试过更改文件扩展名,在关闭它之前刷新 ObjectOutputStream
,更改文件名,但是其中的 none 似乎可以解决问题。显然,我需要了解为什么我的文件是 0 字节(因此阻止我检索任何数据)以及为什么我在读取文件时遇到 EOF 错误。
这里是使用的代码:
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()
创建一个 .mov
文件,其中包含 ArrayList
,getHistory()
returns 一个 ArrayList
存储在一个文件中。至少他们应该。
这是使用分别保存和加载移动历史记录的 F 和 G 键时发生的情况。
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;
这是我在使用加载功能时遇到的错误。创建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.handle(PlayingMenu.java:150)
at view.PlayingMenu.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(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(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
您没有关闭任何一个流。
使用 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();
}
我正在做一个游戏项目,我正在创建一个保存功能。我正在使用序列化文件,以便直接保存对象并在以后检索它们。我只需要保存一个 ArrayList<Direction>
,其中 Direction
是一个包含 UP
、DOWN
、LEFT
、RIGHT
、[=19 的自定义枚举=] 和 RESTART
用于特殊情况。
在我的代码中,我创建了一个 ArrayList<Direction>
包含用户从游戏开始以来所做的每一个动作,并制作了一个保存按钮,将 ArrayList 存储在一个文件中。在文件中写入对象似乎没问题,没有抛出错误或其他任何错误。使用从文件中检索对象的加载按钮时,出现 EOF 错误(错误写在代码下方)。
我注意到我的文件是 0 字节,这让我想知道数据是否真的写入了文件,这可以解释 EOF 错误。我试过更改文件扩展名,在关闭它之前刷新 ObjectOutputStream
,更改文件名,但是其中的 none 似乎可以解决问题。显然,我需要了解为什么我的文件是 0 字节(因此阻止我检索任何数据)以及为什么我在读取文件时遇到 EOF 错误。
这里是使用的代码:
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()
创建一个 .mov
文件,其中包含 ArrayList
,getHistory()
returns 一个 ArrayList
存储在一个文件中。至少他们应该。
这是使用分别保存和加载移动历史记录的 F 和 G 键时发生的情况。
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;
这是我在使用加载功能时遇到的错误。创建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.handle(PlayingMenu.java:150)
at view.PlayingMenu.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(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(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
您没有关闭任何一个流。
使用 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();
}