关于java IO流的问题
将对象写到数组中,为啥会出现 java.io.EOFException 异常呢?代码如下:
public class TestObjectStream {
public static void main(String[] args) throws ClassNotFoundException, IOException {
read(ser());
}
//序列化
public static byte[] ser() throws IOException{
Student stu = new Student("张三", 12);
byte[] dest = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(baos));
oos.writeObject(stu);
dest = baos.toByteArray();
baos.close();
oos.close();
return dest;
}
//反序列化
public static void read (byte[] src) throws IOException, ClassNotFoundException{
ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(new ByteArrayInputStream(src)));
Object readObject = ois.readObject();
if(readObject instanceof Student){
System.out.println(((Student) readObject).name);
System.out.println(((Student) readObject).age);
}
ois.close();
}
}
class Student implements Serializable{
public transient String name;
public int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
麻烦各位给看看。
------解决思路----------------------
16行的toByteArray应放在19行的oos.close后面,并且baos.close()不恰当,应删去。
原因:
1. BufferedOutputStream有一个缓冲区,当外层向他写入的字节多于缓冲区大小后,它才向内层的流写入一次数据。一个对象的信息比较小,不足以引起它的刷新,故数据必须要在缓冲流被flush或close后才能被写入内层流。因此toByteArray的调用需要在oos流关闭(外层流close时会调用内层流的close方法)后才可(此时流中才有东西)。
2.baos会随着oos的关闭自动关闭,不需要手动关闭,即使想手动关闭也应该在外层流关闭之后(如果你把baos换成一个文件输出流,现在的代码就会报错,因为缓冲流会在关闭时尝试向一个已关闭的流中写数据)。
------解决思路----------------------
楼上解释的很清晰了...
建议写代码的时候,手动flush...
------解决思路----------------------
手动flush容易降低效率。只有当一些信息要发送的很及时的时候,建议手动刷新flush。(如socket编程发送消息的时候)其他的时候不建议手动刷新。
------解决思路----------------------
引用:Quote: 引用:16行的toByteArray应放在19行的oos.close后面,并且baos.close()不恰当,应删去。
原因:
1. BufferedOutputStream有一个缓冲区,当外层向他写入的字节多于缓冲区大小后,它才向内层的流写入一次数据。一个对象的信息比较小,不足以引起它的刷新,故数据必须要在缓冲流被flush或close后才能被写入内层流。因此toByteArray的调用需要在oos流关闭(外层流close时会调用内层流的close方法)后才可(此时流中才有东西)。
2.baos会随着oos的关闭自动关闭,不需要手动关闭,即使想手动关闭也应该在外层流关闭之后(如果你把baos换成一个文件输出流,现在的代码就会报错,因为缓冲流会在关闭时尝试向一个已关闭的流中写数据)。
你说的很对,谢谢你的耐心解答。我还有两个问题:
1、流关闭之后,还能调用toByteArray(),为什么不会出错呢?
2、你说的很对,外层流关闭时,会调用内层流的关闭方法。我看了看源码,close()实际上调用了flush()。我发现:
(1)似乎只有BufferedOutputStream和BufferedWriter两个流的flush()方法有实质性的作用(清空缓存区,或者说将数据写入内层流),其他的flush()似乎没有作用。
(2)只有FileOutputStream 和FileWriter的close()有实质性的作用(关闭文件),其他的都是关闭内层流或者无作用。
不知道我说的对不对,请指教。
第一个问题:因为ByteArrayOutputStream流的close方法没有实质性的作用(在Doc里面有写到的)。
第二个问题:(1)对的,有些流没有缓冲区,flush没有用;有些流的flush实际上调用了底层(os或硬件)。flush的要求中没有保证它一定要起效,只需要保证调用flush后没有滞留的数据就可以,即本来就不会滞留数据的流的flush基本没用。
(2)其实还有一些网络流等等的close方法是有效的。。探究他们到底是否有效的方法貌似只能查看源码了,但这并没有什么用——每次用完了流关闭它就可以了,不管它到底是否有效。