由于各种原因,我有一个自定义序列化,我将一些相当简单的对象转储到数据文件中。可能有 5-10 个类,生成的对象图是非循环的并且非常简单(每个序列化对象都有 1 或 2 个对另一个序列化对象的引用)。例如:
class Foo
{
final private long id;
public Foo(long id, /* other stuff */) { ... }
}
class Bar
{
final private long id;
final private Foo foo;
public Bar(long id, Foo foo, /* other stuff */) { ... }
}
class Baz
{
final private long id;
final private List<Bar> barList;
public Baz(long id, List<Bar> barList, /* other stuff */) { ... }
}
id 字段仅用于序列化,因此当我序列化到文件时,我可以通过记录到目前为止已序列化的 ID 来写入对象,然后为每个对象检查其子对象是否已序列化并写入那些没有的,最后通过写入其数据字段和与其子对象对应的 ID 来编写对象本身。
令我困惑的是如何分配 id。我想了想,分配ID似乎有三种情况:
- 动态创建的对象 - id 是从递增的计数器分配的
- 从磁盘读取对象 -- id 是从存储在磁盘文件中的数字分配的
- 单例对象——在任何动态创建的对象之前创建对象,以表示始终存在的单例对象。
我怎样才能正确处理这些?我觉得我在重新发明轮子,必须有一种成熟的技术来处理所有的情况。
澄清:就像一些切线信息一样,我正在查看的文件格式大致如下(忽略了一些不相关的细节)。它经过优化,可以处理大量密集的二进制数据(数十/数百 MB),并能够在其中散布结构化数据。密集的二进制数据占文件大小的 99.9%。
该文件由一系列用作容器的纠错块组成。每个块可以被认为包含一个由一系列数据包组成的字节数组。可以连续读取一个数据包(例如,可以知道每个数据包的结尾在哪里,然后下一个数据包立即开始)。
因此,该文件可以被认为是存储在纠错层之上的一系列数据包。这些数据包中的绝大多数都是不透明的二进制数据,与这个问题无关。然而,这些数据包中的一小部分是包含序列化结构化数据的项目,形成了一种由数据“岛屿”组成的“群岛”,这些数据“岛屿”可以通过对象引用关系链接起来。
所以我可能有一个文件,其中数据包 2971 包含一个序列化的 Foo,数据包 12083 包含一个序列化的 Bar,它引用数据包 2971 中的 Foo。(数据包 0-2970 和 2972-12082 是不透明的数据包)
所有这些数据包都是不可变的(因此考虑到 Java 对象构造的约束,它们形成了一个非循环对象图),因此我不必处理可变性问题。它们也是通用Item
接口的后代。我想做的是将任意Item
对象写入文件。如果Item
包含对文件中已经存在的其他Item
s 的引用,我也需要将它们写入文件,但前提是它们尚未写入。否则,当我读回它们时,我将需要以某种方式合并它们的副本。