catch/finally中不应使用 writer.flush()

在开发中遇到了一个问题,关闭流的时候会出现某种莫名其妙的错误。后来一个巧合看到了这个解决方法。

先看问题(知道答案以后,才知道是这里出错了)

FileWriter writer = null;
String file="D:\\test.txt";
try{
	writer = new FileWriter(file);
	//某些处理后
	writer.flush();
	writer.close();
}catch(Exception e){
	try {
		if(writer != null){
			writer.flush();
			writer.close();
		}
	} catch (IOException e1) {
		e1.printStackTrace();
	}
}

碰巧看到的那段描述,如下:

方法可能因为checked exception导致清理流或资源失败 

这种方法可能无法清理(关闭,处置)流,数据库对象,或者其他的资源,需要一个明确的清除操作。

一般来说,如果一个方法打开一个流或其他资源,方法应该使用try/ finally块来保证流或资源清理方法返回之前。

这种错误模式在本质上是一样的OS_OPEN_STREAM和ODR_OPEN_DATABASE_RESOURCE错误模式,而是基于一个不同的(希望更好)静态分析技术。见韦默和Necula,查找和防止运行时错误处理错误,对分析技术的描述。 

 

刚开始看到这段话,也是一脸懵逼,我明明在catch中使用了 writer.close() 方法了,为什么还说我没清理流。。。

想了好久才把注意力转移到这个flush()方法上:

FileWriter的flush()方法是从OutputStreamWriter中继承来的,其作用就是清空缓冲区并完成文件写入操作的

 

跟踪flush方法,一直到内部sun.nio.cs.StreamEncoder,找到其实现:

public void flush() throws IOException {
	 synchronized (this.lock) {
	      ensureOpen();
	      implFlush();
	}
}

再跟踪ensureOpen()方法:

private void ensureOpen() throws IOException {
	if (!this.isOpen)
		throw new IOException("Stream closed");
	}
}

 

终于找到了,原来这里会抛出异常。

我的理解是,同时使用write.flush();  write.close();两个方法。如果flush发生了异常,就会中断程序,把异常抛出来,就不会执行close方法。那么这个流实际上还是没有清理的。但是如果只使用write.close(); 那么会首先执行flush();,即使执行过程中flush发生了异常,也不会抛出来,还是会close的。

所以我最终的解决方案是:在catch/finally中不使用write.flush();,只是用write.close();

FileWriter writer = null;
String file="D:\\test.txt";
try{
	writer = new FileWriter(file);
	//某些处理后
	writer.flush();
	writer.close();
}catch(Exception e){
	//nothing
}finally{
	try {
		if(writer != null){
			writer.close();
		}
	} catch (IOException e1) {
		e1.printStackTrace();
	}
}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值