错误原因
先直接说错误原因
当使用对象流时,对象头和对象内容一起被写入输出流,而读取时也需要以相同的顺序读取对象头和对象内容
如果读取时的顺序与写入时的顺序不一致,或者在写入或读取对象头和对象内容之间更改了流的状态,则会出现 java.io.StreamCorruptedException: invalid stream header
异常
发生报错的代码
首先可以看一下我的这段代码
客户端使用含有Socket
连接的对象输出流向服务器发送了一条Message
信息,后续接着发送一个User
对象
// 告知服务器进行登录服务Message ask = new Message();ask.setMesType(MessageType.MESSAGE_LOGIN);oos.writeObject(ask);// 发送User信息oos.writeObject(user);
而在服务器,同时有两个地方通过对象输入流从这一个对象输出流读取信息
1号读取Message
对象
2号读取User
对象
/**1号对象输入流*/ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());// 读取功能请求Message ask = (Message) ois.readObject();function = ask.getMesType();System.out.println(function);
/**2号对象输入流*/// 获取客户端数据,使用对象输入流获取User对象 ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); User user = (User) ois.readObject();
此时当服务器代码运行到2号对象输入流是,出现了java.io.StreamCorruptedException: invalid stream header: 7372001
的错误信息
经过查找资料,发现原因
在这个例子中,客户端使用同一个对象输出流依次发送了 Message
和 User
对象,但服务器端使用了两个不同的对象输入流同时读取这个输出流,这导致两个输入流读取的顺序可能不同,从而导致异常
简单说就是
对象输出流序列化数据时,会把数据的数据格式(可以理解为数据存在的形式、在代码中的位置等等)写在流的对象头中,以供于输入流按照格式进行读取
通俗点说
一个工人在做事之前,需要先拿到经理人给的表格,这张表格上写了他要干什么,先做什么后做什么
而当1号对象输入流读取了Message
对象后,Message
对象就被消耗掉了,2号对象输入流读取时,会直接从User
对象这里读起
但是2号对象拿到的这张表格和1号对象拿到的是一样的,上面写了Message
在最前面,然后是User
,可是2号读取时发现Message
不见了,于是报错了
如何修改
为了避免这种异常,最好保证一个输出流对应一个输入流
在类的最前面定义广域的输入流
ObjectInputStream ois; // 对象输入流,用于读取客户端发送消息
随后在读取时都使用这一个输入流去读取输出流
ois = new ObjectInputStream(socket.getInputStream());// 读取功能请求Message ask = (Message) ois.readObject();function = ask.getMesType();System.out.println(function);
// 获取输出流,用于返回登录信息ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());