<JavaEE> 文件IO -- 数据流和文件内容操作(Reader 和 Writer 、InputStream 和 OutputStream)

目录

一、数据流概述

二、流的关闭

2.1 使用 close() 方法

2.2 使用 try-finally

2.3 使用 try-with-resources

三、字符流的读写

3.1 Reader 类

3.2 Writer 类

四、字节流的读写

4.1 InputStream 类

4.2 OutputStream 类


一、数据流概述

1)在 Java 中,文件的操作分为两类
操作文件系统

通过 File 类,在系统中进行增、删、查等操作。

操作文件内容通过 数据流对象,在文件中读取或写入内容。(下文介绍该类)
2)什么是数据流?
数据流是一个抽象概念,水流可以流动,而数据也具有跟水流类似的特点,同时两者也都可以被容器容纳。
3)与文件的类型分类类似,数据流也有两种分类
字符流

文本文件是指保存合法字符的文件,字符以字符串形式保存。以字符形式传输的流对象,被称为字符流。

字节流二进制文件是指文件保存的是二进制数据。以字节形式传输的流对象,被称为字节流。
Java标准库中提供的用于读写文件的流对象有很多类,但是这些类都可以归纳到上述两个大的种类中。
4)流也分为输入流和输出流
每一个种类的流对象,都会有自己的输入流和输出流,在Java中也使用不同的类来表示。
字符流输入流类:Reader
输出流类:Writer
字节流输入流类:InputStream
输出流类:OutputStream
下文将介绍上述流对象的使用。

二、流的关闭

1)流为什么需要关闭?

这里的流是指文件的数据流,每打开一个文件,就会在内存中建立一个PCB。

PCB通过文件描述符表对这些打开的文件进行描述,不使用文件了却不关闭文件,则文件描述附表会一直被占用。

类似于内存泄漏,上述的情况就造成了文件资源泄露

文件描述符表有存储上限的,一旦没有关闭的文件超过文件描述符表的上限,就会抛出异常。

虽然 Java 有垃圾回收机制,但该机制适用于内存资源的回收。而此处泄露的是文件资源。

因此,只有在使用完毕后,关闭流,才能释放文件描述符表这样的文件资源,才不会造成文件资源泄露。

2)怎么关闭流对象?

流对象主要通过以下三种方式进行关闭:

<1>使用 close() 方法
<2>使用 try-finally
<3>使用 try-with-resources

2.1 使用 close() 方法

每个数据流的类,通常都会有一个 close() 方法,用于将这个流的对象关闭。
使用方式:直接用流对象调用 close() 方法即可。
缺点:直接用流对象调用 close() 方法固然可行,但程序如果结构复杂,极可能出现忘记调用,或虽然代码中有调用 close(),却因为代码结构问题或抛出异常问题,而无法执行到这个方法。

2.2 使用 try-finally

try-finally 语法的含义是执行 try 代码块中的代码,无论这些代码是正常执行完毕还是抛出异常,最终都必须执行 finally 代码块中的代码。

语法演示:

try{//创建流对象;//需要执行的代码;
}finally{流对象.close();
}

2.3 使用 try-with-resources

Java 还提供了一种更简洁明了的方式,来帮助程序员更好的管理资源。

try-with-resources 是指将使用后需要关闭的资源,在 try 关键字后使用 () 进行包裹,这样在程序运行出 try 代码块后,() 中包裹的资源将被自动释放。

语法演示:

try( //创建流对象,将需要在代码块运行完成后关闭的资源放在这里 ){//需要执行的代码;
}
在下文的代码演示中,将统一使用这种关闭文件资源的方式。

三、字符流的读写

字符流通过 Reader 类对数据进行读,Reader 是一种输入流。
字符流通过 Writer 类对数据进行写,Writer 是一种输出流。
Reader 类和 Writer 类都是抽象类,创建实例时需要使用他们的子类。

3.1 Reader 类

Reader 使用 read() 方法读取数据,read() 方法如果返回 -1 表示读取到文件末尾,read() 方法有以下三种方法重载
read() :无参数,一次读取一个字符。
read(char[] cbuf) :以数组为参数,最多读取 cbuf.length 字符的数据到数组中,返回实际读取的字符数量。
read(char[] cbuf, int off, int len) :以数组为参数,最多读取 cbuf.length 字符的数据到数组中,会从数组的第 off 个元素开始,将 len 长度的字符填入数组中,返回实际读取的字符数量。

代码演示使用 read() 方法:

//存在当前文件,路径为"C:/Test/A/test.txt",内容为"加油gogogo";public static void main(String[] args) throws IOException {//打开文件C:/Test/A/test.txt;try(Reader reader = new FileReader("C:/Test/A/test.txt")){while (true){//读取一个字符;int ch = reader.read();//判断是否到达文件末尾;if (ch == -1){break;}//打印读取到的字符;System.out.println((char)ch);}}}//运行结果:
加
油
g
o
g
o
g
o

代码演示使用 read(char[] cbuf) 方法:

//存在当前文件,路径为"C:/Test/A/test.txt",内容为"加油gogogo";public static void main(String[] args) throws IOException {//打开文件C:/Test/A/test.txt;try(Reader reader = new FileReader("C:/Test/A/test.txt")){while (true){//创建一个数组,用来存储读取到的字符;char[] cbuf = new char[1024];//将读取到的字符存入cbuf数组中,返回实际读取到的字符个数;int len = reader.read(cbuf);//判断是否到达文件末尾;if (len == -1){break;}//打印cbuf数组中的字符;for (int i = 0; i < len; i++){System.out.print(cbuf[i]);}}}}//运行结果:
加油gogogo

3.2 Writer 类

Writer 使用 write() 方法写入数据,write() 方法有以下五种方法重载
write(int c) :每次写入一个字符。
write(String str) :每次写入一个字符串;
write(char[] cbuf) :每次写入多个字符;
write(String str, int off, int len) :每次写入一个字符串,从字符串中的off位置开始去写,写len长度;
write(char[] cbuf, int off, int len) :每次写入多个字符,从字符数组中的off位置开始去写,写len长度;
由于写入的数据可能保存在缓冲区,未来得及写入文件中。因此,为确保我们可以及时看到写入的内容,Writer 类提供了 flush() 方法,用于刷新缓冲区。

代码演示使用 write(int c) 方法:

//存在当前文件,路径为"C:/Test/A/test.txt",内容为"加油gogogo";public static void main(String[] args) throws IOException {//打开文件C:/Test/A/test.txt;try(Writer writer = new FileWriter("C:/Test/A/test.txt")){//在文件中写入对应字符串;writer.write("我的愿望是,世界和平!");//刷新缓冲区;writer.flush();}}//运行结果:打开文件 C:/Test/A/test.txt ,
发现原来的内容"加油gogogo"被替换为"我的愿望是,世界和平!"

通过上述代码,我们可以发现,原先文件中的文本内容被覆盖了。

在上述代码中,每次写入新的文本前,都会将原有的文本先清空再写入。
如果不想清空原有文本,而是在原有文本之后继续写入,则需要在打开文件时,在

 FileWriter 的构造方法的参数中填入另一个 boolean 类型的参数。当参数为 true 时,则表示追加文本。

代码演示追加文本:

//存在当前文件,路径为"C:/Test/A/test.txt",内容为"加油gogogo";public static void main(String[] args) throws IOException {//打开文件C:/Test/A/test.txt ,参数中添加true;try(Writer writer = new FileWriter("C:/Test/A/test.txt",true)){//在文件中写入对应字符串;writer.write("我的愿望是,世界和平!");//刷新缓冲区;writer.flush();}}//运行结果:打开文件 C:/Test/A/test.txt ,
发现内容为"加油gogogo我的愿望是,世界和平!"

四、字节流的读写

字节流通过 InputStream 类对数据进行读,InputStream 是一种输入流。
字节流通过 OutputStream 类对数据进行写,OutputStream 是一种输出流。
InputStream 类和 OutputStream 类都是抽象类,创建实例时需要使用他们的子类。

4.1 InputStream 类

InputStream 使用 read() 方法读取数据,read() 方法如果返回 -1 表示读取到文件末尾,read() 方法有以下三种方法重载
read() :无参数,一次读取一个字节。
read(byte[] b) :以数组为参数,最多读取 b.length 字节的数据到数组中,返回实际读取的字节数量。
read(byte[] cbuf, int off, int len) :以数组为参数,最多读取 b.length 字节的数据到数组中,会从数组的第 off 个元素开始,将 len 长度的字节填入数组中,返回实际读取的字节数量。

代码演示使用 read() 方法:

//存在当前文件,路径为"C:/Test/A/test.txt",内容为"abc"; public static void main(String[] args) throws IOException {//打开文件C:/Test/A/test.txt;try (InputStream is = new FileInputStream("C:/Test/A/test.txt")){while (true){//读取一个字节;int n = is.read();//判断是否到达文件末尾;if(n == -1){break;}//打印;System.out.printf("%c ",n);System.out.println(n);}}}//运行结果:
a 97
b 98
c 99

代码演示使用 read(byte[] b) 方法:

//存在当前文件,路径为"C:/Test/A/test.txt",内容为"abc"; public static void main(String[] args) throws IOException {//打开文件C:/Test/A/test.txt;try (InputStream is = new FileInputStream("C:/Test/A/test.txt")){while (true){//创建一个数组,用来存储读取到的字节;byte[] b = new byte[1024];//将读取到的字节存入b数组中,返回实际读取到的字节个数;int len = is.read(b);//判断是否到达文件末尾;if(len == -1){break;}//打印;for(int i=0;i<len;i++){System.out.printf("%c ",b[i]);System.out.println(b[i]);}}}}//运行结果:
a 97
b 98
c 99
根据使用的字符集的不同,一个中文字符通常会占用两到三个字节。如果我们需要从文件中读取中文字符会非常麻烦。
因此,可以使用 Scanner 类,来帮助我们从字节流结果中获取中文字符。

代码演示字节流获取中文字符的方法:

//存在当前文件,路径为"C:/Test/A/test.txt",内容为"我的愿望是,世界和平!"; public static void main(String[] args) throws IOException {//打开文件C:/Test/A/test.txt;//将字节流通过 Scanner 类转换为字符流,指定通过“utf8”字符集进行转换;try (InputStream is = new FileInputStream("C:/Test/A/test.txt");Scanner sc = new Scanner(is,"utf8")){//循环判断是否有下一行;while (sc.hasNext()){//获得下一行;String str = sc.next();//打印;System.out.println(str);}}}//运行结果:
我的愿望是,世界和平!

4.2 OutputStream 类

OutputStream 使用 write() 方法写入数据,write() 方法有以下三种方法重载
write(int b) :每次写入一个字节。
write(char[] cbuf) :每次写入多个字节;
write(char[] cbuf, int off, int len) :每次写入多个字符,从字符数组中的off位置开始去写,写len长度;
由于写入的数据可能保存在缓冲区,未来得及写入文件中。因此,为确保我们可以及时看到写入的内容,OutputStream 类提供了 flush() 方法,用于刷新缓冲区。
由于字节流传输的是字节数据,但我们仍需要以字符形式输入,因此下文将以两种将字符转换为字节的方法分别进行演示。

代码演示使用 write(int b) 方法(以 getBytes() 转换字符的方式):

//存在当前文件,路径为"C:/Test/A/test.txt";public static void main(String[] args) throws IOException {//打开文件C:/Test/A/test.txt;try(OutputStream writer = new FileOutputStream("C:/Test/A/test.txt")){//需要在文件中写入的字符串;String str = "我的愿望是,世界和平!";//将字符转换为字节并写入文件;writer.write(str.getBytes());//刷新缓冲区;writer.flush();}}//运行结果:
打开文件 C:/Test/A/test.txt ,
文件内容为"我的愿望是,世界和平!"

代码演示使用 write(int b) 方法(以 PrintWriter 包裹流对象的方式):

//存在当前文件,路径为"C:/Test/A/test.txt";public static void main(String[] args) throws IOException {//打开文件C:/Test/A/test.txt;try(OutputStream writer = new FileOutputStream("C:/Test/A/test.txt")){//使用PrintWriter类将输入的字符自动转换为字节;PrintWriter printWriter = new PrintWriter(writer);//写入文件;printWriter.write("我的愿望是,世界和平!");//刷新缓冲区;writer.flush();}}//运行结果:
打开文件 C:/Test/A/test.txt ,
文件内容为"我的愿望是,世界和平!"

阅读指针 -> 《网络编程》

链接生成中........

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

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

相关文章

[c]零钱兑换

题目比较简单&#xff0c;看答案就能看懂什么意思 #include<stdio.h> int main() {int count 0;int n;scanf("%d", &n);for (int i 0; i < n; i){for (int k 0; k <n/2; k){for (int j 0; j < n/5 ; j){if (i 2 * k 5 * j n){count;}}}}p…

【Python基础】迭代器

文章目录 [toc]什么是迭代可迭代对象判断数据类型是否是可迭代类型 迭代器对可迭代对象进行迭代的本质获取可迭代对象的迭代器通过迭代器获取数据StopIteration异常 自定义迭代器__iter__()方法__next__()方法判断数据类型是否是可迭代类型自定义迭代器案例分离模式整合模式 fo…

这套软件测试技巧|软测经典面试题真的有用,今天面试大部分都遇到了!!!

祝同学们都能够顺利找到心仪的工作拿高薪&#xff0c;废话不多说&#xff0c;下面上题了~ 46、您以往是否曾经从事过性能测试工作&#xff1f;如果有&#xff0c;请尽可能的详细描述您以往的性能测试工作的完整过程。 &#xff08;以自己最熟悉的性能测试项目为例&#xff09; …

【ARM Trace32(劳特巴赫) 高级篇 20 -- SNOOPer 使用介绍】

请阅读【Trace32 ARM 专栏导读】 文章目录 Trace32 SNOOPer 介绍SNOOPer 主要功能:SNOOPer 使用场景SNOOPer.ERRORSTOPSNOOPer.ModeSNOOPer.PCSNOOPer.RateSNOOPer.SELectSNOOPer.SIZESNOOPer.TDelaySNOOPer.TOutSNOOPer.TValueSNOOPer PC 采样Trace32 SNOOPer 介绍 在 Laut…

什么是面向切片编程?

面向切片&#xff08;Aspect-oriented Programming&#xff0c;AOP&#xff09;是一种软件开发的方法论&#xff0c;它旨在通过将横切关注点从主要业务逻辑中分离出来&#xff0c;提供更高层次的模块化和可维护性。它通过将跨越多个对象、类或组件的共同功能&#xff08;称为横…

可惜+悲伤+唉=emmo...

拟合曲线&#xff1a; 参考论文&#xff1a;黄河清.NURBS曲面逆向造型关键算法的研究与应用 [D].西北工业大学,2004 三次NURBS曲线控制点的计算 首先给出拟合曲线的具体步骤&#xff1a; 1、节点矢量的求解方法为&#xff1a; 采用积累弦长参数化法&#xff0c;即&#xff1…

应用ICP-MS实验PFA烧杯耐腐蚀带刻度反应杯的特点分析

聚四氟&#xff08;PFA&#xff09;烧杯可用于痕量分析、同位素分析等实验&#xff0c;ICP-MS实验室适用。半导体、多晶硅、光伏电子 锂电池行业均适用。杯体刻度清晰&#xff0c;方便观察&#xff0c;尖嘴方便倾倒溶液。 可溶性聚四氟乙烯烧杯特性&#xff1a; 1、透明&…

如何定制专属app:定制app教程

《如何定制专属app&#xff1a;探索app定制的秘密》 什么是app定制 在当今数字化时代&#xff0c;应用程序&#xff08;app&#xff09;已经渗透到我们生活的方方面面&#xff0c;从社交娱乐到工作学习&#xff0c;app无处不在&#xff0c;尽管市场上有着众多的app供我们选择…

(企业 / 公司项目)微服务项目解决跨域问题:

前后端分离项目中前端出现了跨域的问题 在网关模块配置文件中添加 配置 application.properties # 允许请求来源&#xff08;老版本叫allowedOrigin&#xff09; spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedOriginPatterns* # 允许携带的头信息 spri…

经典基本电路

USB电路 USB差分走线的阻抗为90欧:差分对10mil宽的走线以及5mil的间距,两边包地15/20mil以上厚度(SI9000计算阻抗) USB2.0接口电路&#xff1a; USB3.0接口电路&#xff1a; USB HUB电路: HDMI电路 HDMI差分走线的阻抗为100欧:差分对6mil宽的走线以及5mil的间距,两边包地15/20…

PADS的使用

目录 一、PADS常规操作1.1 常用快捷键1.2 Logic相关设置 二、Logic库操作2.1 逻辑库2.2 封装库2.3 元件库 一、PADS常规操作 PADS安装好了之后&#xff0c;主要使用下面三个软件&#xff1a; Logic&#xff1a;画原理图文件&#xff0c;也可以使用OrCAD导入Router&#xff1a;…

解决maven报错 ‘parent.relativePath‘ of POM

错误提示 parent.relativePath of POM io.renren:renren-fast:3.0.0 (D:\wzyProjets\gulimail\renren-fast\pom.xml) points at com.wzy.gulimail:gulimail instead of org.springframework.boot:spring-boot-starter-parent, please verify your project structure错误分析 子…

windows10下jdk安装

文章目录 windows10下jdk安装说明what安装包下载执行安装包验证是否安装成功 windows10下jdk安装 说明 操作系统&#xff1a;windows10 版本&#xff1a;1.8 what JDK(Java Development Kit) 是 Java 语言的软件开发工具包 安装包下载 https://www.oracle.com/java/techn…

RabbitMQ插件详解:rabbitmq_recent_history_exchange【RabbitMQ 七】

&#x1f38f;&#xff1a;你只管努力&#xff0c;剩下的交给时间 &#x1f3e0; &#xff1a;小破站 rabbitmq_recent_history_exchange 前言插件介绍工作原理工作原理概述&#xff1a;底层实现&#xff1a; 配置和使用配置插件的详细步骤&#xff1a; 实例演示场景描述&#…

【JAVA】黑马MybatisPlus 学习笔记【二】【核心功能】

2.核心功能 刚才的案例中都是以id为条件的简单CRUD&#xff0c;一些复杂条件的SQL语句就要用到一些更高级的功能了。 2.1.条件构造器 除了新增以外&#xff0c;修改、删除、查询的SQL语句都需要指定where条件。因此BaseMapper中提供的相关方法除了以id作为where条件以外&…

2023.12.13 libstdc++ undefined reference to GLIBCXX

如何升级linux的libstdc.so …/thirdparty/lib/rbdl/librbdl_urdfreader.so: undefined reference to std::ios_base_library_init()GLIBCXX_3.4.32’

Proxmox创建Windows虚拟机

文章目录 下载ISO安装文件上传 下载ISO安装文件 下载地址&#xff1a;https://www.xitongzhijia.net/ 也可去官网进行下载 上传 将下载的ISO文件上传到Proxmox 选择ISO文件进行上传 上传后再ISO镜像中可以看到安装文件 点击创建虚拟机 填写名称&#xff0c;不能填写中文 镜…

被围绕的区域[中等]

一、题目 给你一个m x n的矩阵board&#xff0c;由若干字符X和O&#xff0c;找到所有被X围绕的区域&#xff0c;并将这些区域里所有的O用X填充。 示例 1&#xff1a; 输入&#xff1a;board [["X","X","X","X"],["X",&qu…

aardio网页组件:webPageOperation

webPageOperation是webview的初步封装&#xff0c;用来网页填表、操作网页。可操作web.form、web.view、web.view2等浏览器组件。 使用方法 首先把webPageOperation.aardio&#xff08;源码在后面&#xff09;放到~\lib\godking目录下&#xff0c;然后新建窗口项目&#xff…

HarmonyOS开发入门HelloWorld及工具安装

下载与安装DevEco Studio 在HarmonyOS应用开发学习之前&#xff0c;需要进行一些准备工作&#xff0c;首先需要完成开发工具DevEco Studio的下载与安装以及环境配置。 进入DevEco Studio下载官网&#xff0c;单击“立即下载”进入下载页面。 DevEco Studio提供了Windows版本和…