当前位置: 代码迷 >> J2SE >> 关于java IO流的有关问题
  详细解决方案

关于java IO流的有关问题

热度:178   发布时间:2016-04-23 19:41:03.0
关于java IO流的问题
将对象写到数组中,为啥会出现  java.io.EOFException 异常呢?代码如下:
public class TestObjectStream {
public static void main(String[] args) throws ClassNotFoundExceptionIOException {
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方法是有效的。。探究他们到底是否有效的方法貌似只能查看源码了,但这并没有什么用——每次用完了流关闭它就可以了,不管它到底是否有效。
  相关解决方案