gpt4 book ai didi

java - 存储和管理(正确反序列化对象以及反序列化后如何使用它们

转载 作者:行者123 更新时间:2023-12-02 01:31:48 25 4
gpt4 key购买 nike

我想使用来自具有使用(反)序列化的保存/加载功能的类的数据加载和渲染多个对象到游戏世界,但我无法弄清楚如何正确地将它们重新引入程序,因为它们包含 transient 对象渲染/显示它们是必需的。

我第一次运行程序时,它尝试从不存在的名为“Data.txt”的 txt 文件加载数据。该程序创建一个新的 Data.txt 文件,向其中添加一个名为“campfire”的 Campfire 对象并保存它。只要程序运行,它就会渲染到屏幕上(这部分工作正常)。关闭程序并重新启动后,它应该检查文件,找到它并加载 ArrayList“数据”以及之前保存/序列化的篝火对象。然后它向其中添加另一个相同类型的对象并渲染它们。这部分在我的 Campfire 类的 render 方法中抛出 NullPointerException。

这是主类:

public class MainClass extends ApplicationAdapter{
public static SpriteBatch batch;

private Data data;
private Campfire campfire;

@Override
public void create () {
batch = new SpriteBatch();

data = new Data();
data.load();

campfire = new Campfire();
data.addCampfire(campfire);

System.out.println(data.getSize());
data.save();
}

@Override
public void render () {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

batch.begin();
data.render(batch);
batch.end();
}

加载所有文件的类:

public class Data {
private String filename;
private ArrayList<Campfire> data;

public Data() {
data = new ArrayList<Campfire>();
filename = "Data.txt";
}

public void save(){
try {
FileOutputStream file = new FileOutputStream (filename);
ObjectOutputStream out = new ObjectOutputStream (file);

out.writeObject(data);
out.close();
file.close();
}catch (IOException e) {e.printStackTrace();}
}

public void load() {
try {
FileInputStream file = new FileInputStream (filename);
ObjectInputStream in = new ObjectInputStream(file);

data = (ArrayList<Campfire>)in.readObject();
in.close();
file.close();
}
catch (IOException io) {System.out.println("File not found.");}
catch (ClassNotFoundException ex) {System.out.println("Cant load from file.");}
}

public void addCampfire(Campfire object) {
data.add(object);
}
public void render(SpriteBatch batch) {
for(int i = 0;i < data.size(); i++) {
Campfire camp = data.get(i);
camp.render(batch);
//data.get(i).render(batch);
}
}

public Campfire get(int index) {
return data.get(index);
}

public void set(int index, Campfire object) {
data.set(index, object);
}

public int getSize() {
return data.size();
}

这是在 render() 中抛出 NullPointerException 的类:

public class Campfire implements Serializable{
private transient Texture img;
private int id;

public Campfire() {
img = new Texture("campfire.png");
}

public void render(SpriteBatch batch) {
batch.draw(img, 200,200, 2000,2000);
}

原因是纹理“img”不存在,因为我需要使用 transient 关键字,因此它不会被保存到数据文件或从数据文件加载。

我需要一种不同的方式来根据我从中加载的数组列表创建对象。我无法使用 arrayList 中的对象,因为它们无法渲染(必须将 transient 关键字分配给 Texture() 对象 - 它不可序列化)。我看过很多教程并阅读了大量有关该主题的文章,但我找不到一篇提到如何重新引入该对象,以便我可以利用其依赖于不可(反)序列化部分的函数。

这是我的问题:有没有比我的尝试更好的方法(再次创建对象,然后为其分配反序列化值?我不知道如何在反序列化过程后正确加载和使用“数据”ArrayList,我很感谢关于如何将他们重新引入该程序。

提前致谢,中号

最佳答案

我建议不要为此使用 java 序列化。它在序列化格式的大小方面具有优势,但根据我的经验,它使用起来有点痛苦。您遇到过这种痛苦,因为您无法序列化该 Texture 对象,因为它不是Serialized。您通过将其标记为暂时性来避免该问题,这是一个错误。可能有一些解决方法可以处理您不拥有的对象 - 注册一些处理程序,但说实话,我不知道详细信息,因为我避免了它。

相反,选择像 json 这样友好的格式。这意味着您的序列化数据文件会更大一些,但是您可以打开它并读取它并查看保存的内容。

而且...libgdx 附带了一些工具。有关使用情况,请参阅他们的 wiki 页面 here

还有其他选择 - 比如谷歌 gson 库,但为什么不坚持使用 libgdx 的工具 - 我发现它们非常可靠。

只是一个额外的警告 - 如果您在 Android 中使用某种代码混淆/最小化工具,则需要将其配置为不重命名您序列化的任何对象,因为它确实依赖于包和对象名称进行反序列化。如果您保存游戏状态,然后更改对象的名称/包,然后尝试加载该游戏状态,这也是需要注意的。

关于java - 存储和管理(正确反序列化对象以及反序列化后如何使用它们,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55927557/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com