Как читать ObjectInputStream без знания того, что было сериализовано?

1

Ниже приведен пример кода, где 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();
}
Теги:
serialization

2 ответа

2
Лучший ответ

Я хотел бы предложить отдельное решение (или, по крайней мере, вариант) для @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);
}
1

Сначала вы должны сериализовать заголовок, сообщающий вам, что является содержимым остальной части вашего файла. Таким образом, первое, что вы deserialize, это заголовок (другими словами, представление структуры файла).

редактировать

Сначала вы должны знать, какие типы объектов вы будете сериализовать, тогда вы можете создать парсер для заголовка.

Я не могу представить полный пример, но я могу помочь структурировать ваш заголовок. Если вы манипулируете строкой, списком-строкой и картой, то ваш заголовок может выглядеть так:

List<String> header = new List<String>();
header.add("list-of-string");
header.add("string");
header.add("map");
  • 0
    Любой фрагмент кода, чтобы помочь мне в этом?
  • 0
    Ненужные. Оператор instanceof скажет вам, что на самом деле представляет собой каждый объект.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню