【IO流】缓冲流

news2024/10/6 22:29:30

缓冲流

    • 1. 概述
    • 2. 作用
    • 3. 字节缓冲流
      • 3.1 构造方法
      • 3.2 代码示例
    • 4. 字符缓冲流
      • 4.1 构造方法
      • 4.2 特有方法
      • 4.3 代码示例
        • 4.3.1 `readline()`方法示例
        • 4.3.2 `newline()`方法示例
    • 5. 字节缓冲流提高效率的原理
    • 6. 注意事项

文章中的部分照片来源于哔站黑马程序员阿伟老师处,仅用学习,无商用,侵权联系删除!

1. 概述

缓冲流(Buffered stream)是指在输入输出流的基础上加入了缓冲机制,通过缓冲来提高读写性能的一种流。

在进行数据读写时,缓冲流会先将数据暂存在缓冲区中,当缓冲区满了或者达到一定条件时才会将数据写入到文件或从文件中读取数据,这样就减少了实际的读写次数,提高了读写效率。

使用缓冲流可以有效地减少对磁盘的访问次数,避免频繁的IO操作,从而改善程序的性能。

原理:底层自带了长度为8192的缓冲区提高性能

常见的缓冲流包括BufferedInputStreamBufferedOutputStream(用于字节流)以及BufferedReaderBufferedWriter(用于字符流)等。

在这里插入图片描述

2. 作用

  1. 提高IO效率:缓冲流可以减少实际的读写次数,通过一次性读取或写入更多的数据到缓冲区中,减少了对磁盘或网络的访问次数,从而提高IO效率。

  2. 减少系统开销:频繁的IO操作会给系统带来较大的开销,而使用缓冲流可以减少IO操作的频率,降低了系统的开销,提升程序的性能。

  3. 提供便捷的操作方法:缓冲流提供了许多便捷的读写方法,如readLine()、write()等,使得读写操作更加方便和灵活。

  4. 自动管理缓冲区:缓冲流会自动管理缓冲区的大小和数据的读写,程序员无需手动管理缓冲区,简化了编程过程。

3. 字节缓冲流

3.1 构造方法

方法名称说明
public BufferedInputStream(InputStream is)把基本流包装成高级流,提高读取数据的性能
public BufferedOutputStream(OutputStream os)把基本流包装成高级流,提高写出数据的性能

BufferedInputStreamBufferedOutputStream 是 Java 中用于提高IO读写性能的缓冲流。它们分别用于包装输入流和输出流,使用了内部缓冲区来优化读写操作。

  1. BufferedInputStream:

    • BufferedInputStream 继承自 FilterInputStream,通过将输入流包装在其中,并在内部维护一个字节数组作为缓冲区,实现了对数据的高效读取操作。
    • 当从 BufferedInputStream 中读取数据时,它会优先从缓冲区中读取数据,只有当缓冲区为空时才会从基础输入流中读取新的数据到缓冲区,这减少了对基础输入流的实际读取次数,提高了读取性能。

    举例:

    try (FileInputStream fis = new FileInputStream("input.txt");
         BufferedInputStream bis = new BufferedInputStream(fis)) {
        
        int data = bis.read(); // 从缓冲流中读取数据
        while (data != -1) {
            System.out.print((char) data);
            data = bis.read();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    
  2. BufferedOutputStream:

    • BufferedOutputStream 继承自 FilterOutputStream,通过将输出流包装在其中,并在内部维护一个字节数组作为缓冲区,实现了对数据的高效写入操作。
    • 当向 BufferedOutputStream 中写入数据时,它会先将数据写入到缓冲区中,只有当缓冲区满了或者调用 flush() 方法时才会将缓冲区中的数据实际写入到基础输出流中,减少了对基础输出流的实际写入次数,提高了写入性能。

    举例:

    try (FileOutputStream fos = new FileOutputStream("output.txt");
         BufferedOutputStream bos = new BufferedOutputStream(fos)) {
        
        String message = "Hello, BufferedOutputStream!";
        byte[] bytes = message.getBytes();
        bos.write(bytes); // 将数据写入到缓冲流中
    
        bos.flush(); // 刷新缓冲区,将数据写入到文件中
    } catch (IOException e) {
        e.printStackTrace();
    }
    

3.2 代码示例

  • 代码示例1
    需求: 利用字节缓冲流拷贝文件(一次读取一个字节)

    package text.IOStream.BufferedStream.BufferedStream01;
    
    import java.io.*;
    
    /*字节缓冲流
    
    | 方法名称                                     | 说明                                     |
    | -------------------------------------------- | ---------------------------------------- |
    | public BufferedInputStream(InputStream is)   | 把基本流包装成高级流,提高读取数据的性能 |
    | public BufferedOutputStream(OutputStream os) | 把基本流包装成高级流,提高写出数据的性能 |
    
    需求:
        利用字节缓冲流拷贝文件(一次读取一个字节)
     */
    public class BufferedStream01 {
        public static void main(String[] args) throws IOException {
            //创建缓冲流对象
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\JavaCode\\code\\codeText01\\src\\text\\IOStream\\BufferedStream\\BufferedStream01\\a.txt"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\JavaCode\\code\\codeText01\\src\\text\\IOStream\\BufferedStream\\BufferedStream01\\b.txt"));
            //读取数据(一次读取一个字节)
            int b;
            while ((b = bis.read()) != -1) {
                bos.write((char) b);
            }
    
            //释放资源
            bos.close();
            bis.close();
        }
    }
    
    
  • 输出结果

    • a.txt
      在这里插入图片描述
    • b.txt
      在这里插入图片描述
  • 代码示例2
    需求:利用字节缓冲流拷贝文件(一次读取一个字节数组)

    package text.IOStream.BufferedStream.BufferedStream02;
    
    import java.io.*;
    
    /*字节缓冲流
    
    | 方法名称                                     | 说明                                     |
    | -------------------------------------------- | ---------------------------------------- |
    | public BufferedInputStream(InputStream is)   | 把基本流包装成高级流,提高读取数据的性能 |
    | public BufferedOutputStream(0utputStream os) | 把基本流包装成高级流,提高写出数据的性能 |
    
    需求:
        利用字节缓冲流拷贝文件(一次读取一个字节数组)
     */
    public class BufferedStream02 {
        public static void main(String[] args) throws IOException {
            //创建缓冲流对象
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:\\JavaCode\\code\\codeText01\\src\\text\\IOStream\\BufferedStream\\BufferedStream02\\a.txt"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:\\JavaCode\\code\\codeText01\\src\\text\\IOStream\\BufferedStream\\BufferedStream02\\b.txt"));
            //读取数据(一次读取一个字节数组)
            byte[] bytes = new byte[1024];
            int b; //定义变量记录每次读取的有效的数据个数
            while ((b = bis.read(bytes)) != -1) {
                bos.write(bytes, 0, b);
            }
    
            //释放资源
            bos.close();
            bis.close();
        }
    }
    
    
  • 输出结果

    • a.txt
      在这里插入图片描述
    • b.txt
      在这里插入图片描述

4. 字符缓冲流

4.1 构造方法

方法名称说明
public BufferedReader(Reader)将基本字符输入流包装成缓冲字符输入流,以提高读取效率。
public BufferedWriter(Writer)将基本字符输出流包装成缓冲字符输出流,以提高写入效率。
  1. BufferedReader:

    • BufferedReader 是 Java 中用于提供缓冲字符输入流的类。它继承自 Reader 类,通过包装基本的字符输入流,如 FileReaderInputStreamReader,并添加缓冲功能,以提高读取字符数据的效率。

    • 举例:以下是一个简单示例,演示如何使用 BufferedReader 从文件中读取数据:

      try (FileReader fileReader = new FileReader("example.txt");
           BufferedReader bufferedReader = new BufferedReader(fileReader)) {
          String line;
          while ((line = bufferedReader.readLine()) != null) {
              System.out.println(line);
          }
      } catch (IOException e) {
          e.printStackTrace();
      }
      
  2. BufferedWriter:

    • BufferedWriter 是 Java 中用于提供缓冲字符输出流的类。它继承自 Writer 类,通过包装基本的字符输出流,如 FileWriterOutputStreamWriter,并添加缓冲功能,以提高写入字符数据的效率。

    • 举例:以下是一个简单示例,演示如何使用 BufferedWriter 将数据写入文件:

      try (FileWriter fileWriter = new FileWriter("output.txt");
           BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) {
          bufferedWriter.write("Hello, WeTab!");
          bufferedWriter.newLine();
          bufferedWriter.write("Welcome to the world of AI.");
      } catch (IOException e) {
          e.printStackTrace();
      }
      

4.2 特有方法

  1. 字符缓冲输入流特有方法
字符缓冲输入流特有方法说明
public string readLine()读取一行数据,如果没有数据可读了,会返回null
  • 细节:
    • readLine()方法在读取的时候,一次读一整行,遇到回车换行结束,但是他不会把回车换行读到内存当中
  1. 字符缓冲输出流特有方法
字符缓冲输出流特有方法说明
public void newLine()跨平台的换行

4.3 代码示例

4.3.1 readline()方法示例
  • 代码示例
    package text.IOStream.BufferedStream.BufferedStream03;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    
    /* 字符缓冲流
    字符缓冲流的构造方法
    
    | 方法名称                      | 说明               |
    | ----------------------------- | ------------------ |
    | public BufferedReader(Reader) | 把基本流变成高级流 |
    | public Bufferedwriter(Writer) | 把基本流变成高级流 |
    
    字符缓冲流特有方法
    
    | 字符缓冲输入流特有方法   | 说明                                         |
    | ------------------------ | -------------------------------------------- |
    | public string readLine() | 读取一行数据,如果没有数据可读了,会返回null |
     */
    public class BufferedStream03 {
        public static void main(String[] args) throws IOException {
            //创建对象
            BufferedReader sr = new BufferedReader(new FileReader("D:\\JavaCode\\code\\codeText01\\src\\text\\IOStream\\BufferedStream\\BufferedStream03\\a.txt"));
            //读取数据
            //细节:
            //readLine()方法在读取的时候,一次读一整行,遇到回车换行结束,但是他不会把回车换行读到内存当中
            String line;
            while ((line = sr.readLine()) != null) {
                System.out.println(line);
            }
            //释放资源
            sr.close();
        }
    }
    
    
  • 输出结果
    • a.txt
      在这里插入图片描述
    • 输出程序
      在这里插入图片描述
4.3.2 newline()方法示例
  • 代码示例
    package text.IOStream.BufferedStream.BufferedStream04;
    
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    
    /*字符缓冲流
    字符缓冲流的构造方法
    
    | 方法名称                      | 说明               |
    | ----------------------------- | ------------------ |
    | public BufferedReader(Reader) | 把基本流变成高级流 |
    | public Bufferedwriter(Writer) | 把基本流变成高级流 |
    
    字符缓冲流特有方法
    
    | 字符缓冲输出流特有方法 | 说明         |
    | ---------------------- | ------------ |
    | public void newLine()  | 跨平台的换行 |
     */
    public class BufferedStream04 {
        public static void main(String[] args) throws IOException {
            //创建对象
            BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\JavaCode\\code\\codeText01\\src\\text\\IOStream\\BufferedStream\\BufferedStream04\\a.txt"));
            //输出数据
            String str = "星空下,月色如水,\n" +
                    "流淌着永恒的誓言,";
            bw.write(str);
            //bw.write("\n\t");//原来代码是这样写的,只不过不同的系统,回车换行符号不一样
            bw.newLine();
            String str1 = "风吹过山川河流,\n" +
                    "将我心意传达到远方。";
            bw.write(str1);
            //释放资源
            bw.close();
        }
    }
    
    
  • 输出结果
    在这里插入图片描述

5. 字节缓冲流提高效率的原理

  1. 缓冲流自带长度为8192的缓冲区

    • 对于字节流而言,缓冲区为8k的字节数组

    • 对于字符流而言,缓冲区为16k的字节数组(一个字符等于两个字节)

  2. 可以显著提高字节流的读写性能

  3. 对于字符流提升不明显,对于字符流而言关键点就是两个特有的方法

在这里插入图片描述

6. 注意事项

  1. Flush操作:缓冲流内部会维护一个缓冲区,数据会先写入缓冲区而非立即写入目标流,因此在关闭流或确保数据已经写入目标流之前,需要调用 flush() 方法手动刷新缓冲区,以防止数据丢失。

  2. 关闭流:使用缓冲流时,应该在不再需要使用流时手动关闭流。可以使用 try-with-resources 结构来自动关闭流,确保资源能够及时释放。

  3. 性能考量:尽管缓冲流能够提高性能,但在某些情况下可能并不适用,例如在面对大文件或对实时性要求较高的情况下,过多的缓冲可能会导致延迟,需根据具体情况进行权衡。

  4. 线程安全性:缓冲流并非线程安全的,如果需要在多线程环境下使用,应该考虑使用同步措施来确保线程安全。

  5. 字符编码:在使用缓冲字符流时,需要注意字符编码的设置,尤其是在涉及跨平台或国际化的情况下,确保正确的字符编码。

  6. 异常处理:在使用缓冲流时,及时捕获和处理可能发生的异常,以避免程序出现意外错误。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1476606.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

html2canvas + JsPDF.js 导出pdf分页时的问题

问题描述 前一段时间 实现了html2canvas jspdf.js 导出pdf的功能 项目当时没有测试做完就先搁置 最近项目要上线发现分页时问题 这篇文章记录一下之前的bug import html2canvas from html2canvas; import JsPDF from jspdf export function savePdf(el, title) {html2canva…

Keepalived双机热备——Haproxy搭建web群集

一、认识keepalived keepalived是一个开源的软件,用于实现高可用性和负载均衡。它主要用于在多个服务器之间提供故障转移和负载均衡的功能。keepalived可以监控服务器的状态,并在主服务器发生故障时自动将备份服务器切换为主服务器,以确保服…

2024.2.28 网络

思维导图 整理面试题 1、什么是回调函数 答:将函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。 2、结构体和共用体的区别 答:结构体的每个成员都会分配内存,…

快讯|Tubi 更新内容库重新定义自己

在每月一期的 Tubi 快讯中,你将全面及时地获取 Tubi 最新发展动态,欢迎🌟星标关注【比图科技】,一起成长变强! Tubi 更新内容库,重新定义自己 Tubi 近日宣布为数千万用户免费提供备受观众喜爱、获奖无数的…

anaconda指定目录创建环境无效/环境无法创建到指定位置

已经设置目录到D盘 创建环境时还是分配到C盘 可能是指定位置没有开启读写权限,如我在这里安装到了anaconda文件夹,则打开该文件夹的属性->安全->编辑 allusers下的权限全都打勾

android开发电子书,android基础编程

内存泄漏是什么? 内存泄漏即 ML (Memory Leak) 指 程序在申请内存后,当该内存不需再使用 但 却无法被释放 & 归还给 程序的现象 内存泄漏有哪些情况,对应的解决方案? 内存泄漏的原因归根到底就是当需…

redis-RedisTemplate.opsForGeo 的geo地理位置及实现附近的人的功能

redis内部使用的是 zset 数据结构存储,如下 import cn.huawei.VideoApplication; import cn.huawei.domain.Jingqu; import cn.huawei.service.JingquService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired…

【Java程序设计】【C00321】基于Springboot的在线租房和招聘平台(有论文)

基于Springboot的在线租房和招聘平台(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的在线租房和招聘平台,本系统有管理员、用户、房东以及公司四种角色; 管理员:首页、个人中心…

【DDD】学习笔记-领域驱动设计参考过程模型

通过领域驱动设计魔方,我们从业务、技术与管理三个维度引入了有助于领域驱动设计的方法和模式,同时梳理了影响领域驱动战略设计的架构因素,确定以“四个边界”为核心对领域逻辑进行控制,规定了领域驱动设计团队必须遵循的纪律&…

java常用环境docker安装

配置目录 rocketmqredismysql不配置binlog配置binlog Nacoszookeeper 本文为精简安装,部分不带容器卷映射,仅供以学习使用。 rocketmq nameservice docker run -d -p 9876:9876 --name rmqnamesrv rocketmqinc/rocketmq sh mqnamesrvbroker docker r…

小狐狸chat2.7.2免授权修复版可用版

小狐狸chat2.7.2免授权修复版可用版 在网络上面找了好几个版本不能使用,今天发布这个仔细测试正常使用 主要功能:独立版无限多开支持分销会员充值自己APP打包小程序万能创作MJ绘图多个国内接口 国外很火的ChatGPT,这是一种基于人工智能技术…

LNMP架构的源码编译环境下部署Discuz社区论坛与wordpress博客

目录 一、编译安装Nginx 1、关闭防火墙 2、安装依赖包 3、创建运行用户 4、解压软件包并编译安装 5、软链接路径优化 6、添加Nginx系统服务 二、编译安装Mysql服务 1、安装依赖环境以及源 2、创建运行用户 3、编译安装 4、修改配置文件 5、数据库目录进行权限调整…

Qt SQLite的创建和使用

重点: 1.SQLite创建数据库内容方法 链接:SQLite Expert Personal的简单使用-CSDN博客 2.和数据库进行链接方法 QSqlDatabase DB; //数据库连接bool MainWindow::openDatabase(QString aFile) {DBQSqlDatabase::addDatabase("QSQLITE"); /…

通过多进程并发方式(fork)实现服务器

以下内容为视频学习记录。 1、父进程accept后返回的文件描述符为cfd以及用于创建连接的lfd; 调用fork()创建子进程后,子进程继承cfd,lfd,通过该cfd与连接过来的客户端通信,lfd对子进程来说没用,可以直接close(lfd); 对于父进程来说&#x…

火灾安全护航:火灾监测报警摄像机助力建筑安全

火灾是建筑安全中最常见也最具破坏力的灾难之一,为了及时发现火灾、减少火灾造成的损失,火灾监测报警摄像机应运而生,成为建筑防火安全的重要技术装备。 火灾监测报警摄像机采用高清晰度摄像头和智能识别系统,能够全天候监测建筑内…

【Kafka系列 06】Kafka Producer源码解析

温馨提示:本文基于 Kafka 2.3.1 版本。 一、Kafka Producer 原理图 生产者的 API 使用还是比较简单,创建一个 ProducerRecord 对象(这个对象包含目标主题和要发送的内容,当然还可以指定键以及分区),然后调…

3G 蜂窝移动通信

4 3G 蜂窝移动通信 第三代 (3G) 蜂窝移动通信系统 -1996 年正式标准名称:IMT-2000。 -工作在 2000 MHz 频段,数据率可达 2000 kbit/s(固定站)和 384 kbit/s(移动站)。 -包括中国通信标准化协会 CCSA (C…

云计算与边缘计算:有何不同?

公共云计算平台可以帮助企业充分利用全球服务器来增强其私有数据中心。这使得基础设施能够扩展到任何位置,并有助于计算资源的灵活扩展。混合公共-私有云为企业计算应用程序提供了强大的灵活性、价值和安全性。 然而,随着分布在全球各地的实时人工智能应…

Leetcode 第 385 场周赛题解

Leetcode 第 385 场周赛题解 Leetcode 第 385 场周赛题解题目1:3042. 统计前后缀下标对 I思路代码复杂度分析 题目2:3043. 最长公共前缀的长度思路代码复杂度分析 题目3:3044. 出现频率最高的质数思路代码复杂度分析 题目4:3045. …

【网络那些事】

【云计算】 云计算:把计算资源放在某个地方,并通过互联网暴露出来,让用户可以按需使用计算资源的方式,就是所谓的云计算 云计算的三种服务: 云平台专业名词 日常叫法 亚马逊云叫法 云服务器 ECS (Elas…