java io流用法,分享 23周 Java 关于IO流部分用法

本文章基于本人工作中碰到一些IO流使用和分析(结合源码),基于JDK1.8。

嵌套IO

部分教程,需要按照顺序一个层一层关闭流

FileInputStream fi;

InputStreamReader ir;

BufferedReader reader;

try{

File file = FileUtils.getFileObj(localPath, tbClearBatchFileLogDto.getRecv_filename());

fi = new FileInputStream(file), "UTF_8");

ir = new InputStreamReader(fi);

reader = new BufferedReader(ir);

//处理业务逻辑

......

}catch(Exception e){

//异常处理

.....

}finally{

try{

//按照包装流关闭,后被包装流关闭的顺序

if(fi!=null){

fi.close();

}

if(ir!=null){

ir.close();

}

if(reader!=null){

reader.close();

}

}catch (IOException e){

e.printStackTrace();

}

}

复制代码

其实按照目前版本,只需要关闭最外层的流即可,即如下

FileInputStream fi;

InputStreamReader ir;

BufferedReader reader;

try{

File file = FileUtils.getFileObj(localPath, tbClearBatchFileLogDto.getRecv_filename());

fi = new FileInputStream(file), "UTF_8");

ir = new InputStreamReader(fi);

reader = new BufferedReader(ir);

//处理业务逻辑

......

}catch(Exception e){

//异常处理

.....

}finally{

try{

//按照包装流关闭,后被包装流关闭的顺序

if(reader!=null){

reader.close();

}

}catch (IOException e){

e.printStackTrace();

}

}

复制代码

其实我们查看BufferedReader源码可以知道,调用BufferedReader的close会再调用被包装流的close。

public BufferedReader(Reader in, int sz) {

super(in);

if (sz <= 0)

throw new IllegalArgumentException("Buffer size <= 0");

this.in = in;

cb = new char[sz];

nextChar = nChars = 0;

}

public void close() throws IOException {

synchronized (lock) {

if (in == null)

return;

try {

in.close();

} finally {

in = null;

cb = null;

}

}

}

复制代码

输出包装流关闭

目前很多包装流如OutputStreamWriter、PrintWriter等教程中,都要求在执行close()之前,执行一下flush()。 我们可以先看看OutputStream对于这两个函数说明

/**

* Flushes this output stream and forces any buffered output bytes

* to be written out. The general contract of flush is

* that calling it is an indication that, if any bytes previously

* written have been buffered by the implementation of the output

* stream, such bytes should immediately be written to their

* intended destination.

*

* If the intended destination of this stream is an abstraction provided by

* the underlying operating system, for example a file, then flushing the

* stream guarantees only that bytes previously written to the stream are

* passed to the operating system for writing; it does not guarantee that

* they are actually written to a physical device such as a disk drive.

*

* The flush method of OutputStream does nothing.

*

* @exception IOException if an I/O error occurs.

*/

public void flush() throws IOException {

}

/**

* Closes this output stream and releases any system resources

* associated with this stream. The general contract of close

* is that it closes the output stream. A closed stream cannot perform

* output operations and cannot be reopened.

*

* The close method of OutputStream does nothing.

*

* @exception IOException if an I/O error occurs.

*/

public void close() throws IOException {

}

复制代码

flush:刷新输出流并强制所有缓冲的字节输出写入。 close:关闭此输出流并释放所有系统资源。

但是我非常好奇,究竟我们close时候底层会不会执行flush。

PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream(), CHARSET));

复制代码

我们以上面代码为例子分析一下。

PrintWriter的close是没有调用flush

public void close() {

try {

synchronized (lock) {

if (out == null)

return;

out.close();

out = null;

}

}

catch (IOException x) {

trouble = true;

}

}

复制代码

OutputStreamWriter的close是没有调用flush

public void close() throws IOException {

se.close();

}

复制代码

而socket获取getOutputStream获取对象需要按照实际实现类来决定,我们以最常见的实现来说明

ByteArrayOutputStream

public void close() throws IOException {

}

复制代码

FilterOutputStream

public void close() throws IOException {

try (OutputStream ostream = out) {

flush();

}

}

复制代码

BufferedOutputStream 继承FilterOutputStream,未重写close

以上各个实现类初步来看,无能完全判断close函数就一定调用flush函数。所以为了降低风险,我们调用close函数之前还是调用flush函数。而且从close实现来看,close关闭的资源还需按照各实现类具体所使用资源,然后自行自行关闭操作。

流的自动关闭

总结: (1)自动关闭的资源对象必须实现Closeable或者AutoCloseable;Closeable继承于AutoCloseable接口,只有一个close方法

public interface Closeable extends AutoCloseable {

/**

* Closes this stream and releases any system resources associated

* with it. If the stream is already closed then invoking this

* method has no effect.

*

*

As noted in {@link AutoCloseable#close()}, cases where the

* close may fail require careful attention. It is strongly advised

* to relinquish the underlying resources and to internally

* mark the {@code Closeable} as closed, prior to throwing

* the {@code IOException}.

*

* @throws IOException if an I/O error occurs

*/

public void close() throws IOException;

}

复制代码

(2)通常过重写close方法来实现资源自动关闭;

(3)自动关闭资源使用try特性,无需显性调用关闭资源方法;于finally一致,最后都会执行。如下:

public static void main(String[] args) {

try(InputStream inputStream = new FileInputStream("f:/bb.txt")) {

}catch (Exception e){

e.printStackTrace();

}

}

复制代码

查看FileInputStream的源码,FileInputStream继承InputStream,InputStream实现Closeable。而本省IO流就需要实现close方法,所以直接可以被try直接调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值