JAVA IO中的缓冲流,PrintStream类和PrintWriter以及System.in获取用户输入流详解

1.缓冲流

在java中,缓x冲流(Buffered Streams)是非常有用的,它们属于处理流的一种,用于提高原始数据流(如文件流,网络流)的读取和写入效率。

 Java 的缓冲流是对字节流和字符流的一种封装,通过在内存中开辟缓冲区来提高 I/O 操作的效率。Java 通过 BufferedInputStream 和 BufferedOutputStream 来实现字节流的缓冲,通过 BufferedReader 和 BufferedWriter 来实现字符流的缓冲。

它们内部维护了一个字节数组缓冲区,当进行读写操作时,先将数据读取到缓冲区或者从缓冲区写入数据,然后再与底层设备进行交互。这种方式减少了与底层设备的直接交互次数,提高了读写的效率。

 缓冲流的基本原理:

  1. 使用了底层流对象从具体设备上获取数据,并将数据存储到缓冲区的数组内
  2. 通过缓冲区的read()方法从缓冲区获取具体的字符数据,这样子就提高了效率
  3. 如果用read方法读取字符数据,并存储到另一个容器当中,直到读取到了换行符,将另一个容器临时存储到数据转成字符串返回,就形成了readLine()功能

字节缓冲流的使用场景

字节缓冲流主要用于提高字节流的读写效率,适用于以下场景:

  1. 文件读写:通过字节缓冲流可以提高文件读写的速度,尤其是对于大文件而言。
  2. 网络通信:通过字节缓冲流可以提高网络数据的读写效率,减少交互次数。
  3. 图像处理:通过字节缓冲流可以加速图像的读取和写入操作。
  4. 音频处理:通过字节缓冲流可以提高音频数据的读写效率。

2.字节缓冲流

 构造方法:

  1. public BufferedInputStream(InputStream in):创建一个新的缓冲输入流,注意参数类型为InputStream
  2. public BufferedOutputStream(OutputStream out):创建一个新的缓冲输出流,注意参数类型为OutputStream
// 创建字节缓冲输入流,先声明字节流
FileInputStream fps = new FileInputStream(b.txt);
BufferedInputStream bis = new BufferedInputStream(fps)// 创建字节缓冲输入流(一步到位)
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("b.txt"));// 创建字节缓冲输出流(一步到位)
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));

 缓冲流的高效

我们通过复制一个 370M+ 的大文件,来测试缓冲流的效率。为了做对比,我们先用基本流来实现一下,代码如下:

// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
try (FileInputStream fis = new FileInputStream("py.mp4");//exe文件够大FileOutputStream fos = new FileOutputStream("copyPy.mp4")){// 读写数据int b;while ((b = fis.read()) != -1) {fos.write(b);}
}
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println("普通流复制时间:"+(end - start)+" 毫秒");

这个是十多分钟过去了还没写入完。

// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("py.mp4"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copyPy.mp4"));){// 读写数据int b;while ((b = bis.read()) != -1) {bos.write(b);}
}
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println("缓冲流复制时间:"+(end - start)+" 毫秒");

 这个只需要 8016 毫秒,如何更快呢?

可以换数组的方式来读写,因为这里定义了一个8kb的缓冲区,这意味着每次调用read方法时,它会尝试读取更多8kb的数据。这就减少了读取操作的次数,每次操作可以处理更多的数据。同样,写入操作也是一次性写入一大块数据,这比单字节写入的效率要高的多。

// 记录开始时间
long start = System.currentTimeMillis();
// 创建流对象
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("py.mp4"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copyPy.mp4"));){// 读写数据int len;byte[] bytes = new byte[8*1024];while ((len = bis.read(bytes)) != -1) {bos.write(bytes, 0 , len);}
}
// 记录结束时间
long end = System.currentTimeMillis();
System.out.println("缓冲流使用数组复制时间:"+(end - start)+" 毫秒");

 3.字符缓冲流

BufferedReader 类继承自 Reader 类,提供了一些便捷的方法,例如 readLine() 方法可以一次读取一行数据,而不是一个字符一个字符地读取。

BufferedWriter 类继承自 Writer 类,提供了一些便捷的方法,例如 newLine() 方法可以写入一个系统特定的行分隔符。

构造方法

  • BufferedReader(Reader in) :创建一个新的缓冲输入流,注意参数类型为Reader。
  • BufferedWriter(Writer out): 创建一个新的缓冲输出流,注意参数类型为Writer。
public class Main {public static void main(String[] args) throws IOException {//创建流的对象BufferedWriter bw =new BufferedWriter(new FileWriter("b.txt"));bw.write("我");bw.newLine();bw.write("是");bw.newLine();bw.write("大帅比");bw.newLine();bw.close();//运行结果:我是大帅比}
}

4.PrintStream类和PrintWriter类

1.PrintStream类

PrintStream类是打印输出流,它可以直接输出各种数据类型的数据。它是OutputStream的子类,提供了一系列用于打印数据的方法,方便输出到控制台或文件。

下面是常用的构造方法:

  • PrintStream(OutputStream out): 创建一个PrintStream对象,指定输出目标为指定的字节输出流。
  • PrintStream(OutputStream out, boolean autoFlush): 创建一个PrintStream对象,指定输出目标为指定的字节输出流,并设置是否在写入操作后自动刷新输出缓冲区。
  • PrintStream(File file): 创建一个PrintStream对象,指定输出目标为指定的文件。
  • PrintStream(String fileName): 创建一个PrintStream对象,指定输出目标为指定文件名对应的文件。

这里讲解一下printf的用法:

他是属于PrintStream类的方法,基本语法是

printStream.printf(format,args);
  1. 这里的format是一个格式字符串,它定义了输出格式
  2. args是一个参数列表,它包含了要格式化的数据 

下面来介绍一下格式化符号:

字符串格式化

  • %s : 输出字符串
System.out.printf("%s", "hello world"); // 输出 "hello world"

整数格式化

  • %d : 输出十进制整数
  • %o : 输出八进制整数
  • %x : 输出十六进制整数
  • %X : 输出大写十六进制整数
System.out.printf("%d %o %x %X", 10, 10, 10, 10); // 输出 "10 12 a A"

 浮点数格式化

  • %f : 输出浮点数
  • %e : 输出科学计数法表示的浮点数(小写e)
  • %E : 输出科学计数法表示的浮点数(大写E)
  • %.nf : 控制小数点后的位数,n为数字
System.out.printf("%.2f %e %E", 3.1415926, 3.1415926, 3.1415926); // 输出 "3.14 3.141593e+00 3.141593E+00"

 就介绍这么多,其他的用法在实际开发中可以边学习边用,反正学了你也记不住。

下面是PrintStream类常用方法代码演示:

import java.io.*;public class Main {public static void main(String[] args) throws IOException {try{//创建PrintStream对象,并指定输出目标为文件PrintStream ps =new PrintStream(new FileOutputStream("b.txt"));//打印字符串ps.print("Hello, ");ps.println("world!");//打印整数ps.printf("The answer ifs %d\n",42);//打印浮点数ps.printf("The value of Pi is %.2f\n",Math.PI);//关闭PrintStreamps.close();}catch (FileNotFoundException e){e.printStackTrace();}}
}

打印结果为:

Hello, world!
The answer ifs 42
The value of Pi is 3.14

 2.PrintWriter类

PrintWriter主要继承Writer,PrintWriter主要用于输出字符,它是可以指定字符编码的,这使得它在处理Unicode字符时更加的灵活。

PrintWriter类的常用构造方法有以下几种:

  1. PrintWriter(Writer out): 创建一个PrintWriter对象,指定输出目标为指定的字符输出流。
  2. PrintWriter(Writer out, boolean autoFlush): 创建一个PrintWriter对象,指定输出目标为指定的字符输出流,并设置是否在写入操作后自动刷新输出缓冲区。
  3. PrintWriter(File file): 创建一个PrintWriter对象,指定输出目标为指定的文件。
  4. PrintWriter(String fileName): 创建一个PrintWriter对象,指定输出目标为指定文件名对应的文件。

 跟上面的PrintStream是差不多的,这里就不举例了

5.System.in获取用户输入

Java 的控制台输入由 System.in 完成。

为了获得一个绑定到控制台的字符流,你可以把 System.in 包装在一个 BufferedReader 对象中来创建一个字符流。

这里的in是静态变量,类型是InputStream

下面是创建 BufferedReader 的基本语法:

第一种方法
InputStreamReader isr =new InputStreamReader(System.in);
BufferReader br =new BufferReader(isr);
第二种方法
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

BufferedReader 对象创建后,我们便可以使用 read() 方法从控制台读取一个字符,或者用 readLine() 方法读取一个字符串。

 System.in 返回的是 InputStream 指向命令行输入的字节流,InputStream 的 read 方法以字节流的方式来读取命令行的输入的数据。
查看源码(InputStream.java)我们常用的有:

1 int System.read()                       //以字节的方式读取输入的第一字符,返回该字符的ASCII码
2 
3 int System.read(byte b[])              //以字节的方式把输入的字符放入byte数组中
4 
5 int System.read(byte b[], int off, int len)   //以字节的方式把输入的字符放入byte数组中  off是起始位置,len是最大读入的字节数。

 使用实例:

//  以字节的方式读取输入的第一字符,返回该字符的ASCII码
int inputOne = System.in.read();  // 输入 abc
System.out.println(inputOne);     // 输出 97 (a 的 ascii 码)
byte[] b = new byte[5];
int length = System.in.read(b);    // 输入 abc
System.out.println(length);          // 输出 4, 包含换行键
System.out.println(Arrays.toString(b));  // 输出 [97, 98, 99, 10, 0]

接下来我们来感受一下不同的使用场景,可以跟着敲一遍

1.使用InputStream读取单个字节

import java.io.*;public class Main {public static void main(String[] args) throws IOException {InputStream input =System.in;int data;try{while ((data=input.read())!=-1){System.out.print((char) data);}}catch (IOException e){e.printStackTrace();}}
}

在这个例子中我们使用InputStream的read()方法来读取单个字节,并打印出来

2.使用BufferedReader读取输入

import java.io.*;public class Main {public static void main(String[] args) throws IOException {BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));try{System.out.println("请输入你的年龄:");int age =Integer.parseInt(reader.readLine());//读取一行数据System.out.println("YOu are"+age+"years old");}catch (IOException e){e.printStackTrace();}}
}

3.读取多个输入直到读取到指定的字符串

import java.io.*;public class Main {public static void main(String[] args) throws IOException {BufferedReader reader =new BufferedReader(new InputStreamReader(System.in));try{String input;System.out.println("Enter Lines of text(type'exit'to quit)");while (!(input= reader.readLine()).equals("exit"))){System.out.println("You entered:"+input);}}catch (IOException e){e.printStackTrace();}}
}

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

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

相关文章

白骑士的PyCharm教学基础篇 1.1 PyCharm简介

系列目录 上一篇:无内容 什么是PyCharm? PyCharm 是由 JetBrains 开发的一款集成开发环境(IDE),专为 Python 编程语言设计。它提供了强大的代码编辑、调试、测试和部署功能,使得 Python 开发更加高效和便…

Linux NFS服务搭建及使用

一、NFS 服务器介绍 nfs ( Network File System )即网络文件系统,其基于 UDP/IP使用 nfs 能够在不同计算机之间通过网络进行文件共享,能使使用者访问网络上其它计算机中的文件就像在访问自己的计算机一样。 二、NFS 服务器的特点 …

阿里云服务器 篇四:404页面模板

文章目录 系列文章tsParticles 404 Templates安装方法效果展示更多系列文章 阿里云服务器 篇一:申请和初始化 阿里云服务器 篇二:搭建静态网站 阿里云服务器 篇三:提交搜索引擎收录 阿里云服务器 篇四:404页面模板 tsParticles 404 Templates 官网:https://github.com/…

Websocket自动消息回复服务端工具

点击下载《Websocket自动消息回复服务端工具》 1. 前言 在进行Websocket开发时,前端小伙伴通常是和后端开发人员同步进行项目开发,经常会遇到后端开发人员接口还没开发完,也没有可以调试的环境,只能按照接口文档进行“脑回路开发…

【源码阅读】osproxy对象存储分布式代理(2)--初始化底层服务和日志器

文章目录 初始化底层服务函数返回类型APPRedis newLangGoConfig()函数initLangGoConfig()函数 初始化日志器 上一章【源码阅读】osproxy对象存储分布式代理(1)下一章 这部分涉及了对于底层服务的初始化和日志器的初始化两部分 // 初始化底层服务&#x…

d3d12.dll 文件缺失如何解决?五种修复丢失问题的方法

d3d12.dll 文件缺失如何解决?它为什么会不见呢?今天,我们将探讨 d3d12.dll 文件的重要性、原因以及丢失时的解决策略。本文将全面介绍 d3d12.dll 文件,并提供五种修复丢失问题的方法。 d3d12.dll文件是什么的详细介绍 d3d12.dll …

6 回归集成:xgb、lgb、cat

这个代码是从kaggle上拷贝过来的: 如何使用三个树模型模块化训练;文本特征如何做,如何挖掘;时间特征的处理;模型权重集成; import pandas as pd import math import numpy as np import joblib import…

【JS逆向课件:第八课:异常处理】

异常处理 首先我们要理解什么叫做**"异常”**? 在程序运行过程中,总会遇到各种各样的问题和错误。有些错误是我们编写代码时自己造成的: 比如语法错误、调用错误,甚至逻辑错误。 还有一些错误,则是不可预料的错误…

vst 算法R语言手工实现 | Seurat4 筛选高变基因的算法

1. vst算法描述 (1)为什么需要矫正 image source: https://ouyanglab.com/singlecell/basic.html In this panel, we observe that there is a very strong positive relationship between a gene’s average expression and its observed variance. I…

OpenAI 推出 GPT-4o mini,一种更小、更便宜的人工智能模型

OpenAI 最近推出了新型人工智能模型 GPT-4o mini,以其较小体积和低成本受到关注。这款模型在文本和视觉推理任务上性能优越,且比现有小型模型更快、更经济。GPT-4o mini 已向开发者和消费者发布,企业用户将在下周获得访问权限。 喜好儿网 在…

ubuntu22.04下YOLOv5 TensorRT模型部署

目录 Ubuntu22.04环境配置 1.1 安装工具链和opencv 1.2 安装Nvidia相关库 1.2.1 安装Nvidia显卡驱动 1.2.2 安装 cuda11.7 安装cuDNN 下载下载 tensorrt 下载仓库TensorRT-Alpha并设置 从yolov5源码中导出onnx文件 ​编辑 利用tensorrt编译onnx模型 编译执行yolov5-t…

spring 中的字节码文件访问 -- classreading 包

位于 spring-core 模块下的 org.springframework.core.type.classreading 包提供了读取类中元数据的功能。其实就是在不加载类的情况下,获取 class 文件中定义的类的相关信息:类名、接口、注解、方法及其注解、字段及其注解等。方便 spring 进行类型或指…

牛客0718B——Arraylist 和LinkedList static修饰变量和方法

目录 Q1:currentTimeMillis是什么? Q2:比较Arraylist 和LinkedList的查找时间 3、相关对比Vector和Arraylist 底层扩容的原理: Q4:static修饰静态代码块 修改1: 修改2: 修改3: 修改1: 修改2: Q5…

入坑树莓派(2)——树莓派4B与手机蓝牙通信

入坑树莓派(2)——树莓派4B与手机蓝牙通信 1、引言 在入坑树莓派(1)中已经搞掂了可视化问题。现在继续开展下一步,尝试与手机通信,一开始是想弄wifi连接的,但发现基于wifi的APP比较难弄,为了降低开发的难度,又因为树莓派板子自带蓝牙模块,所以直接选用蓝牙连接手机…

LabVIEW多串口通信

随着现代工业控制对数据采集和处理效率的要求不断提升,传统的单串口通信已无法满足多通道数据传输与大规模数据存取的需求。开发一种基于LabVIEW的多串口通信及数据存储系统,以提升数据处理速度和存储效率,保障生产线的稳定运行显得尤为重要。…

达梦+flowable改造

原项目springbootflowablemysql模式现需改造springbootflowable达梦&#xff0c; 1.在项目中引入达梦jpa包 引入高版本包已兼容flowable&#xff08;6.4.2&#xff09;liquibase&#xff08;3.6.2&#xff09; 我没有像网上做覆盖及达梦配置 <dependency> …

数据结构之树的存储结构详解与示例(C/C++)

文章目录 树的存储结构1. 顺序存储结构2. 链式存储结构结论 树&#xff08;Tree&#xff09;是一种非常常见的数据结构&#xff0c;它模拟了一种层级或分支结构。树由节点&#xff08;或称为顶点&#xff09;组成&#xff0c;每个节点包含一个值&#xff0c;并且可能有多个子节…

SpringDoc2问题汇总

在项目中尝试使用SpringDoc进行文档生成&#xff0c;在使用过程中遇到一系列的问题加以记录. 1.引入依赖 只是单纯的使用SpringDoc的话不需要引入一些乱七八糟的依赖&#xff0c;如今各种增强和拓展依赖层出不穷&#xff0c;但是随着这些依赖的出现带来的不仅是增强&#xff0…

在学习使用LabVIEW的过程中,需要注意哪些问题?

在学习使用LabVIEW的过程中&#xff0c;需要注意以下问题&#xff1a; 1. 基础知识 图形化编程思维&#xff1a; LabVIEW采用图形化编程方式&#xff0c;与传统的文本编程语言有很大不同&#xff0c;需要适应这种新的编程思维方式。数据流概念&#xff1a; 理解LabVIEW的核心数…

调用第三方接口-OkHttpClient

请求方式 POSTGET POST 单个新增 例如后端接口接收参数为 User user 使用OkHttpClient发送post请求 //封装body信息 JsonObject jsonObject new JsonObject(); jsonObject.put("userName","张三"); jsonObject.put("city","北京");…