По разным причинам у меня есть настраиваемая сериализация, где я выгружаю некоторые довольно простые объекты в файл данных.Может быть 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 предназначено только для сериализации, поэтому, когда я сериализуюсь в файл, я могу записывать объекты, сохраняя запись о том, какие идентификаторы были сериализованы до сих пор, а затем длякаждый объект проверяет, были ли его дочерние объекты сериализованы, и записывает те, которые этого не сделали, и, наконец, записывает сам объект, записывая его поля данных и идентификаторы, соответствующие его дочерним объектам.
Что меня удивляет, так это какназначить идентификаторы.Я думал об этом, и кажется, что есть три случая для назначения идентификатора:
- динамически создаваемых объектов - идентификатор назначается из счетчика, который увеличивает
- чтения объектов изdisk - идентификатор присваивается из номера, хранящегося в файле диска
- singleton objects - объект создается до любого динамически создаваемого объекта, чтобы представлять одноэлементный объект, который всегда присутствует.
Как я могу справиться с этим правильно?Мне кажется, что я заново изобретаю колесо, и должна быть хорошо отработанная методика для обработки всех случаев.
уточнение: просто как некоторая тангенциальная информация, формат файлаЯ смотрю примерно следующее (зачеркнуть несколько деталей, которые не должны быть актуальными).Он оптимизирован для обработки довольно большого количества плотных двоичных данных (десятки / сотни МБ) с возможностью разброса структурированных данных в нем.Плотные двоичные данные составляют 99,9% от размера файла.
Файл состоит из серии блоков с исправленными ошибками, которые служат контейнерами.Каждый блок может рассматриваться как содержащий байтовый массив, который состоит из серии пакетов.Можно читать пакеты по одному за раз (например, можно сказать, где находится конец каждого пакета, а следующий начинается сразу после этого).
Таким образом, файл можно рассматривать каксерия пакетов, хранящихся поверх слоя с исправлением ошибок.Подавляющее большинство этих пакетов представляют собой непрозрачные двоичные данные, которые не имеют ничего общего с этим вопросом.Небольшое меньшинство этих пакетов, однако, составляют элементы, содержащие сериализованные структурированные данные, образующие своего рода «архипелаг», состоящий из «островков» данных, которые могут быть связаны ссылочными ссылками на объекты.
Так что у меня может быть файлгде пакет 2971 содержит сериализованный Foo, а пакет 12083 содержит сериализованный Bar, который ссылается на Foo в пакете 2971. (пакеты 0-2970 и 2972-12082 являются непрозрачными пакетами данных)
Все эти пакеты являются всеминеизменяемыми (и, следовательно, учитывая ограничения конструкции объектов Java, они образуют ациклический граф объектов), поэтому мне не приходится сталкиваться с проблемами изменчивости.Они также являются потомками общего Item
интерфейса.Я хотел бы написать произвольный Item
объект в файл.Если Item
содержит ссылки на другие Item
, которые уже есть в файле, мне нужно также записать их в файл, но только если они еще не были записаны.В противном случае у меня будут дубликаты, которые мне нужно будет как-то объединить, когда я прочитаю их обратно.