java io流中为什么使用缓冲流就能加快文件读写速度

io流是啥

 IO流(Input/Output Stream)是指在程序中用来处理输入输出的抽象概念。在Java和许多其他编程语言中,IO流用于处理文件读写、网络通信等操作。

IO流通常分为输入流和输出流两种类型。输入流用于从外部源(如文件、键盘、网络连接)读取数据到程序中,而输出流则用于将程序中的数据写出到外部目标(如文件、屏幕、网络连接)。

在Java中,IO流主要包括字节流和字符流两种。字节流以字节为单位进行数据传输,适用于处理二进制数据;而字符流以字符为单位进行数据传输,适用于处理文本数据。此外,Java中还提供了各种IO流的实现类和工具类,方便开发者进行各种输入输出操作。

InputStream  用于读取;   OutputStream 是 写入数据

基本使用如下

import java.io.*;

public class FileIOExample {

    public static void main(String[] args) {
        String sourceFilePath = "C:/fileA.txt"; // 源文件路径
        String targetFilePath = "C:/fileB.txt"; // 目标文件路径
        
        try (FileInputStream fileInputStream = new FileInputStream(sourceFilePath);
             FileOutputStream fileOutputStream = new FileOutputStream(targetFilePath)) {
             
           
            int length;
            while (true) { // 读取源文件内容
                int ch=fileInputStream.read();
                if(ch==-1)  break;//读完喽
                fileOutputStream.write(ch); // 将内容写入目标文件
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
//read方法返回的是字节byte,但是实际上使用int来接收,原因如下:
//1.Java中不存在无符号类型,byte有符号,-128-127
//  实际上再按照字节读取数据时,并不需要让这样的数据进行算术运算,期待读到无符号 0->255
//2.read如果读取完毕,返回EOF -1;




//不使用try-with resource
import java.io.*;

public class FileIOExample {

    public static void main(String[] args) throws IOException {
        String sourceFilePath = "C:/fileA.txt"; // 源文件路径
        String targetFilePath = "C:/fileB.txt"; // 目标文件路径

        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;

        try {
            fileInputStream = new FileInputStream(sourceFilePath);
            fileOutputStream = new FileOutputStream(targetFilePath);

            int length;
            while (true) { // 读取源文件内容
                int ch = fileInputStream.read();
                if (ch == -1) break; // 读完了
                fileOutputStream.write(ch); // 将内容写入目标文件
            }
        } finally {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
        }
    }

}

try-with-resources 是 Java 7 引入的一种语法结构,用于自动管理资源的关闭。它可以在代码块结束时自动关闭实现了 AutoCloseable 接口的资源,无需显式调用 close() 方法。

使用 try-with-resources 语句,你只需要在 try 关键字后面的括号中声明和初始化要使用的资源,然后在代码块中使用这些资源。当代码块结束时,不管是否发生异常,try-with-resources 会自动关闭这些资源。

下面是使用 try-with-resources 的基本示例:

try (ResourceType resource1 = new ResourceType(); ResourceType resource2 = new ResourceType()) {
    // 使用资源
} catch (Exception e) {
    // 异常处理
}

在这个示例中,resource1 和 resource2 是实现了 AutoCloseable 接口的资源对象。在 try-with-resources 代码块中,你可以使用这些资源,无需显式地调用 close() 方法。当代码块结束时,无论是否发生异常,这些资源都会被自动关闭。

需要注意的是,资源的声明和初始化是按照声明的顺序进行的,而且可以在同一个 try-with-resources 语句中声明多个资源。

介绍FileInputStream和BufferedInputStream 

FileInputStream的read方法底层确实是通过调用JDK层面的read方法,并且这个JDK层面的read方法底层是使用C语言编写的,以实现高效的文件读取功能。但是它会涉及多次内核态与操作系统交互。当我们使用FileInputStream的read方法读取文件时,首先会触发一次用户态到内核态的切换。这是因为文件读取是一个底层的系统调用,需要在内核态执行。内核态具有更高的权限和更直接的访问硬件的能力。

在内核态中,操作系统会执行相应的文件读取操作,将文件中的数据读取到内核缓冲区中。然后,操作系统再将数据从内核缓冲区复制到Java的用户空间中,最终返回给我们的Java程序。

这个过程中涉及了多次内核态与操作系统的交互,包括用户态到内核态的切换、内核态中的文件读取操作以及内核态到用户态的数据复制。每次内核态与操作系统的交互都需要一定的时间开销,所以在大量的文件读取操作中,减少内核态与操作系统的交互次数可以提高性能。

在文件读取方面,FileInputStream和BufferedInputStream都有各自的优缺点。

FileInputStream是一个基于字节的输入流,它从文件中读取字节数据。使用FileInputStream读取文件时,每次读取都会直接从磁盘中读取一个字节,这样会导致频繁的磁盘I/O操作,从而影响文件读取的效率。

BufferedInputStream则是一个基于字节的缓冲输入流,它利用了缓冲区的机制,每次读取一定量的数据到缓冲区中,然后逐个字节地将数据从缓冲区中读取。因为缓冲区可以预读数据并存储在内存中,所以可以减少磁盘I/O次数,从而提高文件读取的效率。

所以,在读取大文件时,使用BufferedInputStream比FileInputStream更高效,因为它减少了频繁的磁盘I/O操作。但是在读取小文件时,由于缓冲区需要耗费一定的时间来填充,可能会出现BufferedInputStream比FileInputStream慢的情况。

综上所述,选择FileInputStream还是BufferedInputStream,要根据具体的情况来考虑,如果需要读取大文件,使用BufferedInputStream更加高效;如果需要读取小文件,使用FileInputStream可能更快一些。

Java I/O中的缓冲流能够加快文件读写速度的根本原因是

将输入/输出流封装在缓冲区内,在缓冲区中进行读写操作,减少了磁盘或网络I/O的次数,提高了读写效率。

具体来说,BufferedInputStream是一种基于字节的缓冲输入流,它利用了缓冲区的机制,每次读取数据时会先将一定量的数据读入缓冲区,然后逐个字节地将数据从缓冲区中读取。当缓冲区中的数据被读完之后,它会再次从输入流中读取一定量的数据到缓冲区中,继续读取操作。

使用缓冲流读取文件时,它会将文件的一部分数据读取到内存中的缓冲区里,然后程序再从缓冲区中逐一读取数据,这样就避免了每次都直接读取硬盘或网络的I/O操作,从而加快了文件的读取速度。

此外,缓冲流还可以减少系统调用的次数,因为每一次系统调用都需要向操作系统申请资源并返回结果,耗费时间较长。而使用缓冲流可以将多个小的I/O操作合并成一个大的操作,从而减少了系统调用的次数,提高了程序的运行效率。

综上所述,使用缓冲流能够加快文件读写速度的根本原因就是通过缓存数据,减少I/O操作。而BufferedInputStream作为一种基于字节的缓冲输入流,可以有效地实现这一目的。

统计表 

 因为采用不同的缓冲区大小时,数据的传输总量(因此招致磁盘操作的数量)是相同的,表所示为发起read和writel调用的开销。缓冲区大小为1字节时,需要调用read)和write1亿次,缓冲区大小为4096个字节时,需要调用read)和writel24000次左右,几平达到最优性能。设置再超过这个值,对性能的提升就不显著了,这是因为与在用户空间和内核空间之间复制数据以及执行实际磁盘l/0 所花费的时相比,read()和write()系统调用的成本就显得微不足道了

在Java中使用流进行文件上传有几个好处

1. 内存效率:使用流可以一次仅将文件的一部分读入内存,而不需要一次性将整个文件读入内存。这对于大型文件尤其重要,因为它可以节省内存并避免OutOfMemoryError。

2. 网络传输:在文件上传到服务器或从服务器下载时,流可以直接在网络上传输,而不需要将整个文件加载到内存中,可以降低网络传输的延迟。

3. 实时处理:流使得文件可以在传输过程中进行实时处理,例如压缩、加密、解密或其他操作,而无需等待整个文件传输完成。

4. 扩展性:流提供了丰富的API和功能,可以方便地对文件进行读取、写入和处理,同时支持各种类型的文件操作。

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sqyaa.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值