IO流-字节流---java进阶day13

1.IO流

1.I:input

将文件和java程序进行连接,然后java程序就可以读取到文件的数据

2.O:output

将文件和java程序进行连接,然后就可以通过java程序写入数据到文件当中

IO流的应用场景:文件的传输

2.IO流的体系

IO流分为两种,一种是字节流,也称为万能流,计算机中任何东西都是以字节的形式存储,所以字节流可以操控任意类型的文件

另一种则是字符流,字符流是专门用来操作纯文本文件(仅有文字的文件),虽然字节流是万能流,但是在操作纯文本文件时会出现乱码,所以字符流就此诞生

3.字节流

分为字节输入流和字节输出流,

由于字节输入流和字节输出流均为抽象类,所以我们使用对应的子类FileInputStream、FileOutputStream

4.字节输出流:FileOutputStream

使用字节输出流,会将java程序和文件建立管道,因为是字节流,所以我们要写数字

记事本文件会将我们写的数字自动转换成字符向我们展示

[1]FileOutputStream构造方法

创建FileOutputStream对象就可以将java程序和文件建立管道,从而输出数据,FileOutputStream的常用构造方法如下:

第一个构造方法,将文件路径以字符串的形式写入构造方法

第二个构造方法,将文件对象写入构造方法

使用第一个构造方法创建对象时,系统报错

我们抛出异常,这里报错的原因可能是因为我们传入的文件地址不存在对应的文件

为了验证上图猜想,D盘此时是没有A.txt这个文件的

创建好字节输出流对象后,我们运行,发现系统没有报错,

而且A.txt文件还自动生成了

如果关联的文件不存在,系统会自动帮我们创建

那上图为何有异常?--如果磁盘都不存在,想帮我们创建也没办法创建

[2]写出方法:write

创建好输出流对象后,调用write方法便可以写出我们想要的数据

1.写出单个字节

在write方法里写入数字,文件便会根据数字转换成对应字节

使用该方法时也会报错,我们继续抛出异常

IOException是FileNotFoundException的父类,父类比子类更大,所以不再需要FileNotFoundException

写好字节后,右键运行,控制台没有结果,我们要去文件中查找

A.txt对照字节生成了abc

2.写出一个字节数组(一次写出多个字节)

创建一个字节数组,并在里面写入数字,然后将数组装入write方法

运行后,文件中又多出一组abc

3.getBytes

String类中的一个方法,可以将字符串转换成字节数组

那么,我们就可以通过getBytes把我们想写出的字符串转换成字节数组,然后再把这个数组存入write方法,这样就能直接写出我们想要的字符串

文件中就直接生成“你好你好”,十分方便

细节:当关联的文件存在时,会清空现有的内容,再进行写入操作

我们会发现,明明刚才右键运行了那么多次,按道理文件里应该要有很大的abc,但是始终都只有两组abc,

正是因为A.txt是存在的文件,所以我们每运行一次,系统会清空之前写在文件里的内容,然后再进行写入操作

4.追加模式


如果我们想追加内容,不想让之前写的内容被删除,就可以在构造方法里写入true,进入追加模式

此时系统就不会再删除文件中原来的数据

5.写出字节数组的一部分

当我们创建了一个字节数组,并且只想写出数组中的一部分时,可以使用这个方法

其中,off代表从数组中哪个索引开始,len代表写几个

文件中只写了bc,而没有写出a

5.关流

使用完流对象后,就需要调用close方法进行关流,否则会占用资源

6.IO流异常的处理方式(标准关流)

1.JDK7版本之前

使用try catch处理异常,将可能发生异常的代码放入try中,然后用catch抓住

但是这样写还存在安全隐患,如下图

第一行会产生运算异常,导致后续程序崩溃,使得close无法执行,无论如何,我们都需要执行关流操作

7.finally代码块

被该代码块包裹的代码,无论如何都会执行

所以,我们可以把close放入finally代码块

这里报错是因为超出了fos的作用域,fos只能在try大括号里使用,我们提升fos的作用域,如下图

如上图,fos还在报错,提示说没有给fos初始化,但是我们明明在try括号里进行了初始化。如果在fos初始化之前,程序就报错崩溃了,那不就无法初始化了吗

给fos赋为null,并且抓住close的异常后,我们执行代码,如下图

报出的是空指针异常,因为fos没有成功赋值,所以是null,然后又调用了close,所以产生空指针异常。所以,最后一步,判断fos在调用close之前是否为null,是null则无须调用close

8.JDK8版本之后异常处理方式

把我们需要关流的对象放入try的小括号里面,然后大括号里写逻辑,catch还是正常抓获异常

无须再手动调用close方法,使用该格式会自动调用close方法

注意:自定义的类使用该格式,要先实现AutoCloseable接口

如下图,当Demo实现了AutoCloseable接口后,会重写close方法,即使我们没有调用close方法,系统还是自动帮我们调用了重写的close

9.字节输入流:FileInputStream

将文件的内容读取到java程序中,然后进行使用

[1]构造方法

注意:字节输入流关联的文件,如果不存在,不会帮我们自动创建文件,而是报错。如果关联的是文件夹路径,系统也会报错

[2]读取单个字节

一次读取文件中的一个字节,并返回读取到的字节

当读取的文件达到结尾后,继续读取会返回-1,我们可以根据这个特性写循环,进行文件的读取

如果想看到对应的字符,我们直接进行强转即可

[3]读取多个字节

创建一个数组,根据数组的大小决定一次读取几个字节,读取到的字节会存在数组中,返回值是本次读取到了几个字节

如下图,将返回值打印,控制台输出2,说明读到了两个有效字节

读取到的有效字节都存在了数组中,所以我们打印数组才能看到数据

10."读取数组"的原理

如下图,read根据数组长度读取字节个数,第一次读取,读到了97,98。存入数组后,打印数组和返回值,对应的便是97、98还有读取的有效字节个数

第二次读取,读到了99、100,数组原有数据被替换,接着打印数组和返回值,出来的便是99、100

第三次读取,文件中已经读完了4个,只剩101未读,所以本次读取只读到了101,数组原来的数据就只有99被替换,100作为残留数据留在数组中,由于只读到一个,返回值为1

第四次读取,文件中所有数据均被读取,无可读取的数据,所以返回值为-1,数组的两个残留数据还存在数组中,打印数组,出来的便是101、100

11.将字节数组转换为字符串

上面的读取,读出来的全是数字,但是我们要看的是字符串,根据String类的构造方法,便可以实现

根据"返回值不是有效个数则返回-1"这个特点,我们可以写一个循环来读取

如下图,构造方法中放入数组,一次读取2个字节,从0号开始读取,读len个,而len代表读取到的有效字节个数,即2

当读完了文件中所有数据后,再读就会返回-1,即len为-1,while循环就会停止

案例

有一点需要注意,如果我们读取的文件没有1024的大小,就可能会输出默认值0,所以我们应该使用write写出数组的一部分

posted @ 2025-04-20 10:41  直実  阅读(24)  评论(0)    收藏  举报