Ниже приведен пример кода, где List
, String
и Map
были сериализованы и десериализованы. Допустим, мне нужно отправить file
по проводу. Как клиент-получатель должен знать, что десериализация выполняется в порядке списка, строки, карты? Как он должен знать, что делать, чтобы читать объект?
public static void serializeBunchOfObjects() throws FileNotFoundException, IOException {
List<String> foo = new ArrayList<String>();
String str = "foo";
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("foo"));
oos.writeObject(foo);
oos.writeObject(str);
oos.writeObject(map);
oos.close();
}
public static void deserializeBunchOfObjects() throws FileNotFoundException, IOException, ClassNotFoundException {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("foo"));
List<String> foo = (List)ois.readObject();
String str = (String) ois.readObject();
Map<Integer, Integer> mapper = (Map) ois.readObject();
}
Я хотел бы предложить отдельное решение (или, по крайней мере, вариант) для @Lynch.
Когда вы отправляете сообщения своему клиенту, у вас есть набор определенных типов сообщений? Если вы это сделаете, вы можете определить объекты-обертки вокруг тела сообщения, которые могут функционировать как своего рода заголовок.
Вы можете определить FooMessage
которого в качестве членов были поля, которые вы хотите сериализовать:
public class FooMessage
{
private static final long serialVersionUID = 1L;
private final List<String> theList;
private final String string;
private final Map<String, Object> theMap;
}
Затем, вместо сериализации деталей по отдельности, сериализуйте оболочку "
final FooMessage msg = new FooMessage(...);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("foo"));
oos.writeObject(msg);
Таким образом, по крайней мере, у вас есть простой способ определить различные поля, которые будут сериализованы. Дополнительное пространство и время накладных расходов обертки будут чрезвычайно малы.
Теперь вы все еще можете использовать предложение @Lynch о написании String
чтобы сначала обозначить тип сообщения...
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("foo"));
oos.writeUTF("FooMessage");
oos.writeObject(msg);
... или, если количество сообщений довольно невелико, вы можете уйти без строки и просто протестировать тип объекта:
final Object received = ois.readObject();
if (received instanceof FooMessage)
{
...
}
else if (received instanceof BarMessage)
{
}
Окончательный вариант состоит в том, что вы можете наследовать свои конкретные типы сообщений из суперкласса, который содержит тип, выраженный как перечисление:
public abstract class MessageWrapper
{
public MessageWrapper(YourMessageType type)
{
this.type = type;
}
public abstract YourMessageType getType();
}
public class FooMessage extends MessageWrapper
{
public FooMessage()
{
super(YourMessageType.FOO);
}
}
Это позволяет:
final MessageWrapper received = (MessageWrapper) ois.readObject();
switch (received.getType())
{
case FOO:
return handleFoo((FooMessage) received);
case BAR:
return handleBar((BarMessage) received);
}
Сначала вы должны сериализовать заголовок, сообщающий вам, что является содержимым остальной части вашего файла. Таким образом, первое, что вы deserialize, это заголовок (другими словами, представление структуры файла).
редактировать
Сначала вы должны знать, какие типы объектов вы будете сериализовать, тогда вы можете создать парсер для заголовка.
Я не могу представить полный пример, но я могу помочь структурировать ваш заголовок. Если вы манипулируете строкой, списком-строкой и картой, то ваш заголовок может выглядеть так:
List<String> header = new List<String>();
header.add("list-of-string");
header.add("string");
header.add("map");