我正在使用Java(LWJGL)来创建某种游戏,并且我想知道在硬盘中读取和存储数据的最快方法。
游戏的世界是代表3D世界的某种网格,我需要存储有关每个1x1x1大小的多维数据集的数据(或者为了获得更好的分辨率,将来可能会更低)。我目前将每个多维数据集记录保存在一个文本文件中。
每个记录存储32x32x32多维数据集的数据。

现在,每条记录需要625 KB的硬盘内存,读取文件需要16毫秒(在我的计算机中,不做任何其他事情,只读取它)。

我想知道是否有更好的方法,因为我可能每3秒使用一次此方法(多数时候不会,但有时会-需要将帧速率保持在60)。
一种获取相同数据的方式,它将消耗更少的内存,并且读取速度更快。
文本文件仅使用数字,英文字母和一些特殊字符(',''(('')''{''}''-''。'':',也许还有更多)。

我听说Minecraft使用.mca文件,但我不知道它们是否更好,或者如何读取它们。

最佳答案

一种实现所需方法的方法是使用序列化和对象流将二进制数据存储到文件中。本质上,您将存储数组对象或块对象(或称为地形的细分)的对象。这将实现更快的加载时间,因为JVM在加载时不必重新构造每个对象。

使用二进制文件的主要优点是,您无需编写任何算法,甚至在希望存储数据时也无需遍历数据。正如您提到的那样,您希望经常进行存储,这可能是一个很好的解决方案。

这是一个示例,为您提供一些指导。

承担:

class Chunk implements java.io.Serializable {

    private static final long serialVersionUID = 1L;

    Block[][][] chunkBlocks;
    // ... other code //
}


通过在类定义中添加语句implements Serializable,表示该类可用于写入和读取字节流中的对象,从而使您可以存储它们并从文件中读取它们。要注意的另一件事是变量serialVersionUID。这是非常重要的,因为它将告诉流此对象属于哪个类以及是否可以将其强制转换为该类。 (注意:这是一个大概的近似值,但是为了避免冗长,我将为您省去细节)。当实现Serializable接口时,诸如eclipseIntelliJ之类的现代IDE将提示您将该变量添加到类中。他们还将为您提供为其生成唯一ID的选项。建议您确保没有任何冲突。

最后,这是存储对象的方式:

/**
 * Object o         : the object you want to save
 * String filename  : the file path of where you want to save the object
 */
public static void save(Object o, String filename) {

    FileOutputStream fos = null;
    ObjectOutputStream oop = null;

    try {
        fos = new FileOutputStream(filename);
        oop = new ObjectOutputStream(fos);
        oop.writeObject(o);
        oop.flush();
        fos.flush();
        oop.close();
        fos.close();
    } catch (IOException e) {
        e.printStackTrace();
    }

}


并加载一个:

/**
 * @returns Object o : the object stored in the file @ filename
 * String filename   : the file path of where you want to save the object
 */
public static Object load(String filename) {

    FileInputStream in;
    ObjectInputStream ois;

    Object o = null;

    try {
        in = new FileInputStream(filename);
        ois = new ObjectInputStream(in);
        o = ois.readObject();
        ois.close();
        in.close();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
   }

   return o;

}


在上面的代码中,我概括了接受和返回java.lang.Object的函数,但是如果希望拥有专用于特定类的函数,则可以将其更改为Chunk或其他任何形式。

您还提到了Minecraft文件格式,但是这些文件格式非常适合于应用程序,并且基本上都是对其有意义的格式。除此之外,它们不适合您想要的频繁保存,它们在后台块卸载方面更胜一筹。

希望这对您有所帮助!

07-26 05:03
查看更多