java 只需要关闭上层流,关于java IO流的有关问题

关于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换成一个文件输出流,现在的代码就会报错,因为缓冲流会在关闭时尝试向一个已关闭的流中写数据)。

------解决思路----------------------

楼上解释的很清晰了...

08121538.gif

建议写代码的时候,手动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方法是有效的。。探究他们到底是否有效的方法貌似只能查看源码了,但这并没有什么用——每次用完了流关闭它就可以了,不管它到底是否有效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值