[Java EE] 文件IO (二):文件内容读写-----数据流

🌸个人主页:https://blog.csdn.net/2301_80050796?spm=1000.2115.3001.5343
🏵️热门专栏:🍕 Collection与数据结构 (91平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm=1001.2014.3001.5482
🧀Java EE(94平均质量分) https://blog.csdn.net/2301_80050796/category_12643370.html?spm=1001.2014.3001.5482
🍭MySql数据库(93平均质量分)https://blog.csdn.net/2301_80050796/category_12629890.html?spm=1001.2014.3001.5482
感谢点赞与关注~~~
在这里插入图片描述

目录

    • 2.2 数据流-----文件内容读写
      • 2.2.1 字节流
        • 2.2.1.1 InputStream概述
        • 2.2.1.2 FileInputStream概述
        • 2.2.1.3 利用Scanner进行字符读取
        • 2.2.1.4 OutputStream概述
        • 2.2.1.5 FileOutputStream概述
      • 2.2.2 字符流
        • 2.2.2.1 Reader
        • 2.2.2.2 Writer

2.2 数据流-----文件内容读写

文件内容读写的操作中常见的包含以下操作:读文件,写文件,打开文件,关闭文件.
Java中通过"流"这样的一组类进行上述的文件操作.
Java中常见的流分为一下两类:字节流和字符流

  • 字节流:以字节为单位进行读写,包括以下两个类,InputStream和OutputStream.
  • 字符流:以字符为单位进行读写,包括以下两个类,Reader和Writer.
    字节流和字符流后面的用法基本上一样,核心操作就是read读,write写.close关闭.

举例说明:水流
在这里插入图片描述
接水和放水的方式有好几种,可以一次性全部放(取)完,也可以分为多次放(取),文件的读写操作也是同样的道理.

文件的读写可以一次性读取完全部的内容,也可以规定一次性读取的字节数.

2.2.1 字节流

字节流这里读取的文件可以是二进制文件,也可以是文本文件

2.2.1.1 InputStream概述

方法:

修饰符及返回值类型⽅法签名说明
intread()读取⼀个字节的数据,返回-1代表已经完全读完了
intread(byte[] b)最多读取b.length字节的数据到b中,返回实际读到的数量;-1代表以及读完了
intread(byte[] b,int off,int len)最多读取len-off字节的数据到b中,放在从off开始,返回实际读到的数量;-1代表以及读完了
voidclose()关闭字节流

[注意事项]

  • 第二个read方法中给出了一个字节数组,代表的是,我们需要先准备好一个空数组,方法执行完毕之后,就会把读取到的数据填写到byte数组中,其中初始化byte数组的时候,可以指定一次性读取的字节数.也就是说,一次性读取字节数的多少取决于数组的长度,read会尽可能填满数组,如果填不满,能填多少填多少.

举例说明:取食堂打饭
取食堂打饭的时候,我们会先拿上一个空盘子,也就是固定大小的空数组,之后我们把这个盘子递给食堂的阿姨,也就是把空数组递给read方法,但是这里的食堂的阿姨不一样,这里的食堂阿姨不会手抖,会尽可能地把整个盘子都给你打满,如果剩下的饭不多了,食堂阿姨也没有办法,只能把盆子里剩下的所有的饭都给你打上,你也只能吃锅底了.(填不满,能填多少填多少)
在这里插入图片描述

  • 我们看到,前三个方法读取的时候,读取的应该是字节流,但是我们返回值的类型却是int类型,这是为什么呢?
    • 首先,在我们读到文件结束位置的时候,会返回-1,为了有余地表示-1,所以用int.
    • 可以确保杜处的字节,都是正数,都是按"无符号"的方式处理的.
  • 需要注意的是,我们在最后必须要关闭流,否则出现不可预知的bug.
  • InputStream只是一个抽象类,要使用的时候,还得有具体的类去实现.关于InputStream的实现类有很多,基本可以认为不同的输⼊设备都可以对应⼀个InputStream类,(包括蓝牙输入,网卡输入,硬盘输入)我们现在只关⼼从硬盘中读取,所以使用FileInputStream.
2.2.1.2 FileInputStream概述

构造方法:

签名说明
FileInputStream(File file)利⽤File构造⽂件输⼊流
FileInputStream(String name)利⽤⽂件路径构造⽂件输⼊流

第一个构造方法传入的是File对象,也就是通过File类提前创建好的文件对象来构造文件输入流.
第二个方法是通过传入文件的绝对路径或者是相对路径来构造文件输入流.

代码示例:输入效率问题

    public static void main(String[] args) throws IOException {File file = new File("./test.txt");file.createNewFile();try(OutputStream outputStream = new FileOutputStream("./test.txt")){byte[] array = {(byte) 'a',(byte)'b',(byte)'c',(byte)'d'};//注意强制类型转换outputStream.write(array);outputStream.flush();}try(InputStream inputStream = new FileInputStream("./test.txt")){//使用try()的方式来保证最后数据流一定会被关闭byte[] array = new byte[10];//一次读取10个字节while (true){int a = inputStream.read(array);//返回实际读取到的数量if (a == -1){//读取到文件的末尾-1,就停止读取break;}for (int i = 0; i < a; i++) {//这里之所以不写array.length是因为读到文件末尾的时候//最后实际读到的字节数不一定读慢10个字节System.out.println(array[i]);}}}}
public static void main(String[] args) throws IOException {File file = new File("./test.txt");file.createNewFile();try(OutputStream outputStream = new FileOutputStream("./test.txt")){byte[] array = {(byte) 'a',(byte)'b',(byte)'c',(byte)'d'};//注意强制类型转换outputStream.write(array);outputStream.flush();}try(InputStream inputStream = new FileInputStream("./test.txt")){//使用try()的方式来保证最后数据流一定会被关闭while (true){int a = inputStream.read();//返回实际读取到的数量if (a == -1){//读取到文件的末尾-1,就停止读取break;}System.out.println((char) a);}}}

注:OutputStream先不用管,我们先看InputStream的方法.

  • 第一种模式读取数据是每次读取10个字节的数据,但是第二个就是每次读取1个字节的数据.这两种方法相比,第一种方法的效率相对较高,是应为相对第一种方法,第二种方法读取硬盘的频率相对较高,读取硬盘的操作本来就是一个非常低效的操作,所以第二种方法效率相对第一种肯定低一些.
  • 我们知道,在读取完数据之后,输入流一定要被关闭,但是为了把我们的代码写得"优雅"一些,也就是不调用close方法即可关闭输入流,我们就可以把InputStream的创建放入try()中,但是可以这样做有着一定的前提条件,就是InputStream这个类实现了Closeable接口.
    public abstract class InputStream implements Closeable
2.2.1.3 利用Scanner进行字符读取

上述例子中,我们看到了对字符类型直接使用InputStream进行读取是非常麻烦且困难的,所以,我
们使用⼀种我们之前比较熟悉的类来完成该⼯作,就是Scanner类

构造⽅法说明
Scanner(InputStream is, String charset)使⽤charset字符集进行is的扫描读取

从上述Scanner的构造方法中,我们看到,Scanner的其中一个构造方法中,有一个参数就是输入流类型的参数.也就是说,我们在之前使用idea的控制台输入的一些内容,其实本质上就是一种输入流类型的数据.

public static void main7(String[] args) throws IOException {try(InputStream inputStream = new FileInputStream("./test.txt")){//之所以把Scanner放在try中,是因为最后它也要关闭try(Scanner scanner = new Scanner(inputStream)) {//这里Scanner传入的对象是一个输入流对象while (scanner.hasNext()){System.out.println(scanner.next());}}}}
2.2.1.4 OutputStream概述

方法:

修饰符及返回值类型⽅法签名说明
voidwrite(int b)写⼊要给字节的数据
voidwrite(byte[] b)将b这个字符数组中的数据全部写⼊os中
intwrite(byte[] b,int off,int len)将b这个字符数组中从off开始的数据写⼊os中,⼀共写len个
voidclose()关闭字节流
voidflush()重要:我们知道I/O的速度是很慢的,所以,⼤多的OutputStream为了减少设备操作的次数,在写数据的时候都会将数据先暂时写⼊内存的⼀个指定区域⾥,直到该区域满了或者其他指定条件时才真正将数据写⼊设备中,这个区域⼀般称为缓冲区。但造成⼀个结果,就是我们写的数据,很可能会遗留⼀部分在缓冲区中。需要在最后或者合适的位置,调⽤flush(刷新)操作,将数据刷到设备中。

[注意事项]

  • 上面方法的原理和InputStream类的方法相似,这里不再赘述.
  • OutputStream是一个抽象类,要使用具体的类来实现,现在还是只关心写的内容,所以使用FileOutStream
2.2.1.5 FileOutputStream概述

构造方法:

签名说明
FileOutputStream(File file)利⽤File构造⽂件输出流
FileOutputStream(String name)利⽤⽂件路径构造⽂件输出流

示例1:

public static void main(String[] args) throws IOException {try(OutputStream outputStream = new FileOutputStream("./test.txt"){byte[] bytes = {(byte)'a',(byte)'b',(byte)'c'};outputStream.write(bytes);outputStream.flush();}}

[注意事项]

  • 按照写方式打开文件之后,会把==文件中的内容清空,==如果不想把文件中的内容清空,这时候我们就需要给输出流的构造方法中加上一个true,表示以"追加写"的方式打开.
public static void main(String[] args) throws IOException {try(OutputStream outputStream = new FileOutputStream("./test.txt",true){byte[] bytes = {(byte)'a',(byte)'b',(byte)'c'};outputStream.write(bytes);outputStream.flush();}}
  • 如果我们在输出流中的write方法中写入的是数字,也会被ascii转化为字符.

2.2.2 字符流

字符流这里只可以读取文本文件.也就是读取的内容都是可以经过编码表编码为合法字符的.

2.2.2.1 Reader

构造方法:
Reader的构造方法和上述两个类的构造方法使用方法相同,这里不再赘述.
常用方法:
常用方法有两个,一个是read(),这个方法一次读取一个字符.一个是read(char[] cbuf),一次读取指定大小字符的字符串.
[注意事项]

  • 因为这里读取的是文本中的字符,这里常用的第二个read方法数组的类型是char[]类型,由于之前的字节流读取的是字节,所以是byte[].
  • 问题:写在文本文件中的中的如果是中文字符串,中文字符串的每一个字符是3字节,而char[]类型数组中的每一个位置是2字节,那么read(char[] cbuf)是如何做到精准读取的呢?
    解答:实际上,因为Java对上述的代码进行了编码转码,read操作在读取的时候,可以识别出String类型的每一个字符是utf-8编码格式(3字节/字),之后编译器就可以把utf-8格式的字符转码为Unicode(2字节/字)编码方式的字符.

代码演示:

public static void main10(String[] args) throws IOException {try(Reader reader = new FileReader("./test2.txt")){while (true){char[] chars = new char[10];int a = reader.read(chars);//在读取的时候,编译器会自动把汉字String中utf8的编码方式转为char中Unicode的编码方式//其中String中utf8编码方式是3字节,Unicode编码是2字节,char类型正好可以存下2字节if (a == -1){break;}for (int i = 0; i < a; i++) {System.out.println(chars[i]);}}}}
2.2.2.2 Writer

构造方法:略
常用方法:

方法用法
write()一次写一个字符
write(char[] cbuf)一次写多个
write(String str)一次写一个字符串

代码实例:

public static void main9(String[] args) throws IOException {try(Writer writer = new FileWriter("./test2.txt")){char[] chars = {'你','好','世','界'};writer.write(chars);writer.flush();}}

和OutputStream一样,它们在写内容的时候一样会清空文件内容,我们如果我们想重复写入,那么就要在构造方法后面加上true.

public static void main9(String[] args) throws IOException {try(Writer writer = new FileWriter("./test2.txt",true)){char[] chars = {'你','好','世','界'};writer.write(chars);writer.flush();}}

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

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

相关文章

Seal^_^【送书活动第4期】——《Web渗透测试技术》

Seal^_^【送书活动第4期】——《Web渗透测试技术》 一、参与方式二、本期推荐图书2.1 前 言2.2 关于本书2.3 本书读者2.4 图书简介2.5 作者荐语2.6 编辑推荐2.7 目 录 三、正版购买 掌握Web渗透测试技术&#xff0c;提高Web应用安全性。 一、参与方式 1、关注博主的账号。 2、点…

Qt---项目的创建及运行

一、创建第一个Qt程序 1. 点击创建项目后&#xff0c;选择项目路径以及给项目起名称 名称&#xff1a;不能有中文、不能有空格 路径&#xff1a;不能有中文路径 2. 默认创建有窗口类myWidget&#xff0c;基类有三种选择&#xff1a;QWidget、QMainWindow、QDialog 3. m…

ssl证书免费申请指南

同学们可以私信我加入学习群&#xff01; 正文开始 前言一、购买证书二、创建证书三、 验证证书等待出现如下页面&#xff0c;说明申请成功&#xff1a; ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/6b6c1dd11d4c467687318552da7cdbb2.png) 总结 前言 今天为大…

企业必看:镭速教你如何测试内网文件传输效率和稳定问题

在现代商业运作中&#xff0c;企业内部文件传输的效率和稳定性对于数据管理和业务流程极为重要。无论是远程工作还是团队协作&#xff0c;高效的文件传输都能显著提升工作效率。今天镭速小编就教你如何测试内网文件传输效率和稳定问题。 1、磁盘性能&#xff0c;即硬盘的读取和…

类图及类的关系

类图&#xff08;Class Diagram&#xff09;是UML&#xff08;Unified Modeling Language&#xff0c;统一建模语言&#xff09;中的一种图&#xff0c;用于描述系统中类的静态结构&#xff0c;包括类的属性、方法以及类之间的关系。 一、类 类&#xff08;Class&#xff09;…

高级查询(一)

解决需求&#xff1a;Excel都可以轻松搞定 分组查询原理&#xff1a; 语法&#xff1a; SELECT …<列名> FROM <表名> [WHERE<条件表达式> ] GROUP BY 参与分组的列 可以与 聚合函数作用的列 一块显示 注意 SELECT列表中只能包含&#xff1a; 1、被分…

勒索软件漏洞?在不支付赎金的情况下解密文件

概述 在上一篇文章中&#xff0c;笔者对BianLian勒索软件进行了研究剖析&#xff0c;并且尝试模拟构建了一款针对BianLian勒索软件的解密工具&#xff0c;研究分析过程中&#xff0c;笔者感觉构建勒索软件的解密工具还挺有成就感&#xff0c;因此&#xff0c;笔者准备再找一款…

gin框架学习笔记(三) ——路由请求与相关参数

参数种类与参数处理 查询参数 在讲解查询参数的定义之前&#xff0c;我们先来看一个例子&#xff0c;当我打开了CSDN&#xff0c;我现在想查看我的博客浏览量&#xff0c;那么我就需要点击我的头像来打开我的个人主页,像下面这样: 我们现在把浏览器的网址取下来&#xff0c;…

uniapp编译H5解决ios的border-radius失效问题,以及ios满屏显示不全的问题

1.解决方案 .card-itemA {width: 650rpx;height: 326rpx;box-shadow: 0rpx 0rpx 30rpx 14rpx rgba(236, 235, 236, 0.25);background: linear-gradient(180deg, #FFFFFF 0%, rgba(255, 255, 255, 0) 100%);border-radius: 60rpx;overflow: hidden;// 兼容ios的圆角问题transfor…

web入门练手案例(一)

下面是一下web入门案例和实现的代码&#xff0c;带有部分注释&#xff0c;倘若代码中有任何问题或疑问&#xff0c;欢迎留言交流~ 新闻页面 案例描述&#xff1a; 互联网的发展使信息的传递变得方便、快捷&#xff0c;浏览新闻称为用户获取信息的重要渠道。下面将实现一个简…

OrangePi Zero2 全志H616开发学习文档、基础IO蜂鸣器、超声波测距、舵机PWM基础开发

一.平台介绍 OrangePi开发板不仅仅是一款消费品&#xff0c;同时也是给任何想用技术来进行创作创新的人设计的。它是一款简单、有趣、实用的工具&#xff0c;你可以用它去打造你身边的世界。 特性 CPU 全志H616四核64位1.5GHz高性能Cortex-A53处理器GPU MaliG31MP2 Supports…

Nginx解决跨域问题

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 W3C标准&#xff1…