Java 如何在不知道序列化内容的情况下读取ObjectInputStream?
下面是一个示例代码,其中对Java 如何在不知道序列化内容的情况下读取ObjectInputStream?,java,serialization,Java,Serialization,下面是一个示例代码,其中对列表、字符串和映射进行了序列化和反序列化。假设我需要通过电线发送文件。接收客户端如何知道反序列化是按列表、字符串和映射的顺序进行的?他怎么知道要把被阅读的对象投射到什么地方 public static void serializeBunchOfObjects() throws FileNotFoundException, IOException { List<String> foo = new ArrayList<String>();
列表
、字符串
和映射
进行了序列化和反序列化。假设我需要通过电线发送文件
。接收客户端如何知道反序列化是按列表、字符串和映射的顺序进行的?他怎么知道要把被阅读的对象投射到什么地方
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();
}
public static void serializeBunchOfObjects()抛出FileNotFoundException,IOException{
List foo=new ArrayList();
字符串str=“foo”;
Map Map=newhashmap();
ObjectOutputStream oos=新的ObjectOutputStream(新文件输出流(“foo”));
oos.writeObject(foo);
oos.writeObject(str);
oos.writeObject(映射);
oos.close();
}
public static void deserializeBunchOfObjects()引发FileNotFoundException、IOException、ClassNotFoundException{
ObjectInputStream ois=新ObjectInputStream(新文件输入流(“foo”);
List foo=(List)ois.readObject();
String str=(String)ois.readObject();
映射器=(Map)ois.readObject();
}
您应该首先序列化一个头,告诉您文件其余部分的内容。这样,反序列化的第一件事就是头(换句话说,是文件结构的表示)
编辑
首先,您必须知道将序列化哪些类型的对象,然后可以为标头创建解析器
我不能提供一个完整的例子,但我可以帮助您构造标题。如果操纵字符串、字符串列表和映射,则标题可能如下所示:
List<String> header = new List<String>();
header.add("list-of-string");
header.add("string");
header.add("map");
列表头=新列表();
header.add(“字符串列表”);
标题。添加(“字符串”);
标题。添加(“地图”);
我想为@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;
}
这样,至少您有一种简单的方法来定义将序列化的各个字段。包装器的额外空间和时间开销将非常小
现在,您仍然可以使用@Lynch的建议,首先编写一个字符串来表示消息类型
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);
}
“接收客户端如何知道反序列化是按列表、字符串、映射的顺序进行的?”这个问题没有意义。客户机怎么知道它是一个对象流呢?客户端如何知道发送对象的目的是什么?任何客户机-服务器系统都有一个应用程序协议,并且两端都应该实现它。instanceof操作符将告诉您每个对象实际上是什么。
final MessageWrapper received = (MessageWrapper) ois.readObject();
switch (received.getType())
{
case FOO:
return handleFoo((FooMessage) received);
case BAR:
return handleBar((BarMessage) received);
}