【Java基础】I/O流 —— Java中的流都需要关闭吗?

一、为什么要关闭流?

涉及到对外部资源的读写操作,包括网络、硬盘等等的I/O流,如果在使用完毕之后不关闭,会导致资源泄漏以及可能会引起文件锁定等问题。因此,需要在使用完毕之后关闭流。
关闭流是一种资源释放机制,意味着在使用完毕之后归还系统的内存、CPU或者网络等资源,避免资源长时间占用。常见的关闭流的方法是调用close()方法,该方法会将相关的资源释放,可以有效避免导致资源泄漏的问题。
需要注意的是,关闭流的时机非常重要,过早关闭可能会影响正常操作,而过晚关闭则可能导致资源泄漏。在实际开发的时候,使用完毕之后应该及时关闭流。在Java 7之后引入了try-with-resources语法,可以在语法层面上自动关闭流,用法是:

/* 读取文件 */
File file = new File("opsLiya.json");
try (FileInputStream fileInputStream = new FileInputStream(file)) {
    
    
    /* 操作 */
}catch (IOException e){
    
    
    /* 异常处理 */
}

当然也可以使用传统的finally代码块关闭流:

InputStream inputStream = null;
try {
    
    
    inputStream = new FileInputStream("opsLiya.txt");
    /* 操作 */
} catch (IOException e) {
    
    
    /* 异常处理 */
} finally {
    
    
    if (inputStream != null) {
    
    
        try {
    
    
            inputStream.close();
        } catch (IOException e) {
    
    
            /* 异常处理 */
        }
    }
}

二、close方法和flush方法

1.使用close方法

当我们使用输入流的时候,如FileInputStream,对流进行关闭时,直接调用close方法即可。
close方法的底层如下:
在这里插入图片描述

这个close0方法的底层是一个native方法(本地方法)
在这里插入图片描述

此方法进行具体的关闭操作。

2.使用flush方法

当我们使用输出流的时候(即写入数据到文件或者网络中),如BufferedOutputStream,对流进行关闭时,需要先调用flush方法再调用close方法
我们进入到BufferedOutputStream的flush方法的源码可以看到:
在这里插入图片描述

方法注释大概的意思是:刷新此缓冲输出流。这将强制将任何缓冲的输出字节写入底层输出流。
也就是说,在关闭流前调用flush方法,会将缓存中的数据强行刷新到输出目标中,避免数据丢失

三、流按指向分类

Java中的流在指向上可以分为两大类,分别是用于读写内存的流用于读写外部资源(文件、网络等)的流。
比如,用于读写内存的流又可以根据操作对象分为两类,如下:

  1. 操作对象是byte数组:
    1. ByteArrayInputStream
    2. ByteArrayOutputStream
  2. 操作对象是字符串:
    1. StringReader
    2. StringWriter

而用于读写外部资源的流,有如下这些:

  1. FileInputStream和 FileOutputStream:用于字节流读写文件;
  2. FileReader和FileWriter:用于字符流读写文件;
  3. BufferedInputStream和BufferedOutputStream:用于缓存读写字节流提升IO性能;
  4. BufferedReader和BufferedWriter:用于缓存读写字符流提升IO性能;
  5. DataInputStream和DataOutputStream:可以用于读写整数、浮点数等基本类型的字节流;
  6. ObjectInputStream和ObjectOutputStream:用于读写Java对象的字节流;
  7. Socket和ServerSocket:用于网络数据传输;
  8. HttpURLConnection:用于HTTP请求等。

四、不用关闭的流

对于Java中的ByteArrayInputStreamByteArrayOutputStream,它们都是在内存中进行读写操作,不需要涉及到底层的外部资源(如文件、网络等等),因此在使用完毕后不一定需要显式地调用close方法去关闭。它们占用的内存将会被JVM自动回收。
我们可以去到ByteArrayInputStream的close方法实现是一个空方法,如下:
在这里插入图片描述

当然,我们也可以手动释放它们占用的内存——使用try-with-resources语法:

byte[] data = new byte[]{
    
    1, 2, 3, 4, 5};
try (ByteArrayInputStream bis = new ByteArrayInputStream(data);
  ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
    
    
 /* 操作 */
} catch (IOException e) {
    
    
 /* 异常处理 */
}

注意:虽然它的close方法是空实现,但是我们为了保证代码的可读性和健壮性,仍然应该在使用完毕后及时关闭它们。

猜你喜欢

转载自blog.csdn.net/qq_44778023/article/details/131050269