JAVA进阶 (IO流)—— 基本流
创始人
2024-06-03 11:06:31
0

目录

一、前言

二、IO流的分类

三、 字节流

1. 输出流  FileOutputStream

 1.1 FileOutputStream 写数据的三种方式

1.2 FileOutputStream 写数据的两个小问题

2.  输入流  FileInputStream

2.1 FileInputStream 循环读取

2.2 FileInputStream 读数据的两种方式

3. 练习:文件拷贝

四、字符流

 1. 字符输入流 FileReader 

2. 字符输出流 FileWriter

3. 字符流原理分析

五、综合练习

1. 拷贝

2. 文件加密

3. 修改文件中的数据


一、前言

File:表示系统中的文件或者文件夹的路径。(详细见:JAVA进阶 —— File)

 注意: File类只能对文件本身进行操作,不能对写文件里面存储的数据。

IO流:用来读写文件中的数据(可以读写文件、或者网络中的数据 . . . )

二、IO流的分类

流的方向操作文件类型

 纯文本文件:Windows自带的记事本打开能读懂的文件。

三、 字节流

 注意:字节流读取文件的时候,文件中不要有中文。

1. 输出流  FileOutputStream

操作本地文件的字节输出流,可以把程序中的数据写到本地文件中。

书写步骤:

① 创建字节输出流对象

  • 细节1:参数是字符串表示的路径或者File对象都是可以的。
  • 细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的。
  • 细节3:如果文件已经存在,则会清空文件。

② 写数据

  • 细节:write方法的参数是整数,但是实际上写到本地文件中的是整数ASCII上对应的字符。

③ 释放资源

  • 细节:每次使用完流之后都要释放资源。
public class ByteStreamDemo1 {public static void main(String[] args) throws IOException {// 需求: 写一段文字到本地文件中// 1.创建对象// 写出 -> 输出流 OutputStream// 编译时期异常 throws FileNotFoundExceptionFileOutputStream fos = new FileOutputStream("java02\\a.txt");// 2.写出数据fos.write(97);// 3.释放资源fos.close();}
}

 1.1 FileOutputStream 写数据的三种方式

方法名称说明
void write ( int  b )一次写一个字节数据
void write ( byte [ ]  b )一次写一个字节数组数据
void write ( byte [ ] b , int off, int len )一次写一个字节数组的部分数据
public class ByteStreamDemo2 {public static void main(String[] args) throws IOException {// 1.创建对象FileOutputStream fos = new FileOutputStream("java02\\a.txt");// 2.写出数据// ①、一次写一个字符数据fos.write(97); // afos.write(98); // b// ②、一次写入一个字符数组byte[] bytes = { 97, 98, 99, 100, 101 };fos.write(bytes);// ③、一次写一个字符数组的部分数据// 参数一:数组 ;参数二:起始索引 ; 参数三:个数fos.write(bytes, 1, 2); // b c// 3.释放资源fos.close();}
}

1.2 FileOutputStream 写数据的两个小问题

  • 换行写:换行符 \r \n
  • 续写:FileOutputStream("路径", 参数);
  • public class ByteStreamDemo3 {public static void main(String[] args) throws IOException {// 1.创建对象FileOutputStream fos = new FileOutputStream("java02\\a.txt", true);// 2.写出数据String str = "abcdefghijklmn";byte[] bytes = str.getBytes(); // 字符串转换成字节数组fos.write(bytes);// 3.换行// 换行符// windows:00\r\n Linux: \n Mac:\rString str3 = "\r\n";byte[] bytes3 = str3.getBytes();fos.write(bytes3);String str2 = "666";byte[] bytes2 = str2.getBytes();fos.write(bytes2); // 此时一开始并没有换行 需要上写一个换行符// 4.续写// 如果想要续写,打开续写开关即可// 打开位置,创建对象的第二个参数// 默认false:表示关闭,此时创建对象会清空文件// 手动true:表示打开续写,此时创建对象不会清空文件// new FileOutputStream("java02\\a.txt",true);// 5.释放资源fos.close();}
    }

2.  输入流  FileInputStream

  • 操作本地文件的字符输入流,可以把本地文件中的数据读取到程序当中。

书写步骤:

① 创建字节输入流对象

  • 细节:如果文件不存在,就直接报错。

② 读数据

  • 细节1:一次读一个字节,读出来的是数据在ASCII上对应的数字。
  • 细节2:读取到文件末尾时,read方法返回 -1。

③ 释放资源

  • 细节:每次使用完流必须要释放资源。

public class ByteStreamDemo4 {public static void main(String[] args) throws IOException {// 1.创建对象FileInputStream fis = new FileInputStream("java02\\a.txt");// a.txt : abcde// 2.读取数据int b1 = fis.read();System.out.println(b1); // 97System.out.println((char) b1); // 强转: a// 读取不到就会返回 -1// 3.释放资源fis.close();}
}

2.1 FileInputStream 循环读取

read方法:读取数据,而且是读取一个数据移动一次指针

public class ByteStreamDemo5 {public static void main(String[] args) throws IOException {// 1.创建对象FileInputStream fis = new FileInputStream("java02\\a.txt");// a.txt : abcde// 2.循环读取//定义第三方变量int b;while ((b = fis.read()) != -1) {System.out.println((char) b);}// 以下读取方式是错误的//read方法:读取数据,而且是读取一个数据移动一次指针//相当于迭代器的next方法// while (fis.read() != -1) {// System.out.println(fis.read()); // 98 100 -1// }// 释放资源fis.close();}
}

2.2 FileInputStream 读数据的两种方式

方法名称说明
public int read ( )一次读一个字节数据
public int read ( byte [ ] buffer )一次读一个字节数组数据

 注意:一次读一个字节数组的数据,每次读取会尽可能把数组填满。

public class ByteStreamDemo6 {public static void main(String[] args) throws IOException {// 1.创建对象FileInputStream fis = new FileInputStream("java02\\a.txt");// 2.读取数据byte[] bytes = new byte[2];//一次读取多个字节数据:具体读多少,跟数组的长度有关//返回值:本次读取到了多少个字节数据int len = fis.read(bytes);System.out.println(len);String str= new String(bytes);System.out.println(str);//3.释放资源fis.close();}
}

3. 练习:文件拷贝

需求:把D: \aaa\movie . mp4拷贝到当前模块下。
注意:选择一个比较小的文件.不要太大。

public class ByteStreamDemo6 {public static void main(String[] args) throws IOException {// 1.创建对象FileInputStream fis = new FileInputStream("D:\\aaa\\movie.mp4");FileOutputStream fos = new FileOutputStream("java02\\copy.mp4");// 2.拷贝// 需要边读边写int b;while ((b = fis.read()) != -1) {fos.write(b);}// 3.释放资源// 规则: 先开的最后关闭fos.close();fis.close();}
}

 弊端: FileInputStream 一次读写一个字节,速度慢。

 解决方案:FileInputStream 使用 byte[] 数组一次遍历多个数据。

public class ByteStreamDemo6 {public static void main(String[] args) throws IOException {long start = System.currentTimeMillis();// 1.创建对象FileInputStream fis = new FileInputStream("D:\\aaa\\movie.mp4");FileOutputStream fos = new FileOutputStream("java02\\copy.mp4");// 2.拷贝int len;byte[] bytes = new byte[1024 * 1024 * 5]; // 5兆大小while ((len = fis.read(bytes)) != -1) {fos.write(len);}// 3.释放资源fos.close();fis.close();long end = System.currentTimeMillis();//运行时间System.out.println(end - start);}
}

四、字符流

字符流的底层其实就是字节流。

  • 字符流 = 字节流 + 字符集

特点:

  • 输入流:一次读取一个字节,遇到中文时,一次读多个字节再写到文件中。
  • 输出流:底层会把数据按照指定的编码方式,变成字节再写到文件中。

使用场景: 对于纯文本文件进行读写操作。

 1. 字符输入流 FileReader 

书写步骤:

① 创建字符输入流对象

构造方法说明
public FileReader ( File file )创建字符输入流关联本地文件
public FileReader ( String pathname )创建字符输入流关联本地文件
  • 细节:如果文件不存在,就直接报错。

② 读取数据

成员方法说明
public int read ( )读取数据,读到末尾返回 -1
public int read ( char [ ]  buffer )读取多个数据,读到末尾返回 -1
  • 细节1:按字节进行读取,遇到中文,一次读多个字节,读取后解码,返回一个整数。
  • 细节2:读到文件末尾时,read方法返回 -1。

③ 释放资源

成员方法说明
public int close ( )释放资源 / 关流
public class CharStreamDemo1 {public static void main(String[] args) throws IOException {// 1.创建对象并关联本地文件FileReader fr = new FileReader("java02\\a.txt");// 2.读取数据 // 细节1:字符流的底层就是字节流// 默认一个字节一个字节的读取的// 如果遇到中文,就会一次读取多个字节,GBK一次两个字节 UTF-8一次三个字节// 细节2:读取之后,方法底层会进行解码并转换成十进制// 十进制作为返回值 并作为字符集上的数字// 细节3:想要看中文 可以对十进制进行强转//空参readint ch;while ((ch - fr.read()) != -1) {// System.out.println(ch);System.out.println((char) ch);}//带参read:读取数据、解码、强转三者合并,把强转之后字符放进数组//空参的read + 强转类型转换char[] chars = new char[2];int len;while((len = fr.read(chars)) != -1) {//把数组中的数据变成字符串再进行打印System.out.println(new String(chars,0,len));}// 3.释放资源fr.close();}
}

2. 字符输出流 FileWriter

书写步骤:

① 创建字符输出流对象

构造方法说明
public Filewriter ( File file )创建字符输出流关联本地文件
public Filewriter ( String pathname )创建字符输出流关联本地文件
public Filewriter ( File file , Boolean append )创建字符输出流关联本地文件,续写
public Filewriter ( String pathname , Boolean append )创建字符输出流关联本地文件,续写
  • 细节1:参数是字符串表示的路径或者File对象都是可以的。
  • 细节2:如果文件不存在会创建一个新的文件,但是要保证父级路径是存在的。
  • 细节3:如果文件已经存在,则会清空文件,如果不想清空可以打开续写开关。

② 写数据

成员方法说明
void write ( int c )写出一个字符
void write ( String str )写出一个字符串
void write( String str, int off,int len )写出一个字符串的一部分
void write( char [ ] cbuf)写出一个字符数组
void write( char [ ] cbuf,int off, int len)写出字符数组的一部分
  • 细节:如果write方法的参数是整数,但是实际上写到本地文件中的是整数在字符集上对应的字符。

③ 释放资源

  • 细节:每次使用完流之后都要释放资源
public class CharStreamDemo2 {public static void main(String[] args) throws IOException {// 1.创建对象 续写开关打开FileWriter fw = new FileWriter("java02\\a.txt", true);// 2.写数据fw.write(25105); // 写一个字符fw.write("你好?"); // 写一个字符串 9个字节char[] chars = { 'a', 'b', 'c', '我' };fw.write(chars); // 写一个字符数组// 3.释放资源fw.close();}
}

3. 字符流原理分析

① 创建字符输入流对象

  • 底层:关联文件,并创建缓冲区(长度为8192的字节数组)

② 读取数据

  • 底层:
  • 1. 判断缓冲区中是否有数据可以读取
  • 2. 缓冲区没有数据:就从文件中获取数据,装到缓冲区中,每次尽可能装满缓冲区;如果文件中也没用数据时,返回 -1。
  • 3. 缓冲区有数据:就从缓冲区中读取。  空参的read方法:一次读取一个字节,遇到中文一次读多个字节,把字节解码并转成十进制返回。  有参的read方法:把读取字节、解码、强转三步合并,强转之后的字符放到数组当中。

五、综合练习

1. 拷贝

需求:拷贝一个文件夹,考虑子文件夹。

public class Test01 {public static void main(String[] args) {// 1.创建对象表示数据源File src = new File("D:\\aaa\\src");// 2.创建对象表示目的地File dest = new File("D:\\aaa\\dest");// 3.调用方法开始拷贝copydir(src, dest);}public static void copydir(File src, File dest) throws IOException {// 判断目的文件夹是否存在dest.mkdir();// 递归// 1.进入数据源File[] files = src.listFiles();// 2.遍历数组for (File file : files) {if (file.isFile()) {// 是文件 开始拷贝FileInputStream fis = new FileInputStream(file);//dest 是文件夹 不是最终目的地 需要从文件开始到文件结束FileOutputStream fos = new FileOutputStream(new File(dest, file.getName()));byte[] bytes = new byte[1024];int len;while ((len = fis.read(bytes)) != -1) {fos.write(bytes, 0, len);}fos.close();fis.close();} else {// 是文件夹 递归copydir(file, new File(dest, file.getName()));}}}
}

2. 文件加密

需求:
为了保证文件的安全性,就需要对原始文件进行加密存储,再使用的时候再对其进行解密处理。

加密原理:
               对原始文件中的每一个字节数据进行更改,然后将更改以后的数据存储到新的文件中。
解密原理:
               读取加密之后的文件,按照加密的规则反向操作,变成原始文件。

public class Test2 {public static void main(String[] args) throws IOException {// ^ 异或:两边相同false 两边不同true// 1.创建对象关联原始文件FileInputStream fis = new FileInputStream("java02\\girl.jpg");// 2.创建对象关联加密文件FileOutputStream fos = new FileOutputStream("java02\\ency.jpg");// 3.机密过程int b;while ((b = fis.read()) != -1) {fos.write(b ^ 2);}// 4.释放资源fos.close();fis.close();// 解密过程FileInputStream fis = new FileInputStream("java02\\ency.jpg");FileOutputStream fos = new FileOutputStream("java02\\redu.jpg");int b;while ((b = fis.read()) != -1) {fos.write(b ^ 2);}fos.close();fis.close();}
}

3. 修改文件中的数据

需求:

文本文件中有以下的数据:
             2-1-9-4-7-8
将文件中的数据进行排序,变成以下的数据:
             1-2-4-7-8-9

​
public class Test3 {public static void main(String[] args) throws IOException {// 1.读取数据FileReader fr = new FileReader("java02\\a.txt");StringBuilder sb = new StringBuilder();int ch;while ((ch = fr.read()) != -1) {sb.append((char) ch);}fr.close();System.out.println(sb);// 2.排序String str = sb.toString();String[] arrStr = str.split("-");// 定义数组用于存储数据进行排序ArrayList list = new ArrayList<>();for (String s : arrStr) {int i = Integer.parseInt(s);list.add(i);}System.out.println(list);// sort: 默认升序排序Collections.sort(list);System.out.println(list);// 3.写出数据FileWriter fw = new FileWriter("java02\\a.txt");// 打印结果: 1-2-4-7-8-9 通过索引遍历 -》 普通for循环for (int i = 0; i < list.size(); i++) {if (i == list.size() - 1) {fw.write(list.get(i) + "-");} else {fw.write(list.get(i));}}fw.close();}
}​

相关内容

热门资讯

清朝有很多有名的历史人物,能给... 清朝有很多有名的历史人物,能给大家说几个清朝的历史人物吗?林则徐,张之洞,乾隆皇帝,曾国藩,朱耷,这...
曹丕的“太子四友”指的是谁 曹丕的“太子四友”指的是谁首先说,曹丕这四个,陈群司马懿是顶级的谋士和政治家,吴质有些小聪明,朱铄不...
在这次遇难者中存在了几名幸存者... 在这次遇难者中存在了几名幸存者。这句话是不是逻辑错误这句话的逻辑没有问题,有问题的是用词不当。遇难者...
在中国古代,有许多充满哲学智慧... 在中国古代,有许多充满哲学智慧的成语典故、寓言故事,如...在中国古代,有许多充满哲学智慧的成语典故...
清澈的意思是什么,… 清澈的意思是什么,…清净而明澈清而透明【造句】看着他清澈而又天真的眼眸,我的心久久不能平静……
蚂蚁森林合种爱情树一方退出怎么... 蚂蚁森林合种爱情树一方退出怎么找回来两个人合种的爱情树,我退出来,我怎么再次加入进去继续合作那个树?...
有好看的古代修炼小说推荐吗? 有好看的古代修炼小说推荐吗?古代重生穿越修炼......让我帮你找一下这些古代修炼的小说,找到这些类...
女主重生爱上前世辜负的人 女主重生爱上前世辜负的人重生我是你正妻渣女重生之竹马重生之弃渣重生之夫君可欺重生之换我疼你重生妇归来...
华胥引有广播剧吗 华胥引有广播剧吗现有的华胥引的广播剧是忆语广播剧社出品的,只有十三月和杯(这个是错字,请无视,居然输...
选文韩麦尔先生在说了,我的朋友... 选文韩麦尔先生在说了,我的朋友们我就要离开你们呢了,再见了银头鲑鱼tj75rt6yturdrruv ...
中通快递从北京保定市到广东揭阳... 中通快递从北京保定市到广东揭阳普宁要多久?中通快递从北京保定市到广东揭阳普宁要多久?从北京到广东需要...
关于离婚悲伤的歌曲 关于离婚悲伤的歌曲关于离婚悲伤的歌曲林俊杰《可惜没如果》 张靓颖《我走以后》 金志文《流着泪说分手》...
形容文笔差怎么说啊? 形容文笔差怎么说啊?哥哥姐姐,麻烦问下,我是做文员的,形容文案方面的工作很差应该怎么说啊?粗鄙怎么样...
我想做未婚妈妈,可行吗? 我想做未婚妈妈,可行吗?没关系吧?我同学好多他们妈妈都是30岁以后省得他们,都没事啊,但是如果你自己...
如何在两个excel表格里筛选... 如何在两个excel表格里筛选出重复的名字如何在两个excel表格里筛选出重复的名字1、电脑打开EX...
且试天下 哪些小说是用白绫做武... 且试天下 哪些小说是用白绫做武器的?神雕侠侣吖- -..小龙女一开始就是用白绫的聊斋 辛十四娘嘿嘿~...
自带高冷体质,笑起来温暖又治愈... 自带高冷体质,笑起来温暖又治愈的星座,你了解吗?虽然天生高冷体质,但是笑起来特别的温暖治愈的新作用天...
火星未解之谜 火星未解之谜多列举一些,每个事例最好长一点,谢啦~“火星人脸”, “地表被水冲击河道”,“原始大气和...
我是1991年10月4号生的,... 我是1991年10月4号生的,是什么星座啊有的说是处女座有的说是天平座,糊涂了,到底是什么啊很负责任...
梦见白狐狸,然后当时我骑着自行... 梦见白狐狸,然后当时我骑着自行车,我想躲开它,他很凶的的追赶我,最后它向我扑了过来,然后我就醒乐.你...