当前位置: 首页 > news >正文

4. IO Stream

文章目录

  • 一、相对论理解IO流
  • 二、汉语文学理解流
  • 三、图解IO流
  • 四、俩亲爹InputStream和OutputStream
  • 五、FileInputStream字节流读取文件
  • 六、FileOutputStream字节流写入文件
  • 七、buff缓冲复制文件
    • 1. 例一(无buff)
    • 2. 例二(有buff)
  • 八、buffered字节缓冲流和装饰设计模式
  • 九、FileReader和FileWriter,俩专门来搞txt文件的
  • 十、BufferedReader和BufferedWriter
  • 十一、一次性讲解剩余的N个流(扩展课)Java里那些极其骚的IO流
  • 十二、Apache Common IO
    • 1. 例一
    • 2. 例二(arrayList的妙用)
  • 十三、补充
  • 十四、内容出处

一、相对论理解IO流

官方文档
在这里插入图片描述
在这里插入图片描述
        不仅是水,数据也是如此。例如,你发了一个视频给你的朋友,数据就从你的电脑上流通到了ta的电脑上,这个过程就叫数据流。

二、汉语文学理解流

为什么中国人用”流"这个字,而外国人用"stream"来代替?
这个字的偏旁是三点水,所以古人说的流一定跟水有关。可以引申为数据在流动时也像水一样流动
在这里插入图片描述

三、图解IO流

官方文档在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
        当我们打开一个记事本读取里面的内容时,数据从本地存储设备流入记事本程序。因此,相对于记事本程序而言,数据是输入的;相对于本地存储设备而言,数据是输出的。

四、俩亲爹InputStream和OutputStream

Package java.io
重点关注这俩:
在这里插入图片描述
在这里插入图片描述
filechannel(文件通道):并发编程 现在可以先忽略

五、FileInputStream字节流读取文件

第一部分代码出处
菜鸟教程
① 字节流:以字节为单位去读和写,好处在于可以读写任何文件(图片、.mp3、.mp4等都可以化为字节)
② FileInputStream又称为字节流的原因:它是按照字节来读的
在这里插入图片描述

package com.practice.demo3;import org.junit.Test;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;public class TestIo {private final static int SIZE = 4096;@Testpublic void inputFile() throws IOException {FileInputStream fileInputStream = new FileInputStream("file\\1.txt");
//        System.out.println("------------该部分代码来自上述网页--------------------------");/*System.out.println("按字节读取, read()返回读取到的字节");int by = 0;// 如果读到文件末尾, 则会返回-1while ((by = fileInputStream.read()) != -1){System.out.println(by);}*//*System.out.println("read(byte[] b)返回读取到的字节个数");byte[] buf = new byte[30];int len = fileInputStream.read(buf);System.out.println(len);System.out.println(Arrays.toString(buf));System.out.println(new String(buf, 0, len));*//*System.out.println("创建一个字节数组");int len = 0;byte[] buf = new byte[SIZE];while((len = fileInputStream.read(buf))!= -1){System.out.println(new String(buf, 0, len));}*/
//        System.out.println("---------------------------------------------------");System.out.println("结合一下菜鸟教程的案例:");int by;while ((by = fileInputStream.read()) != -1){System.out.print((char)by);}fileInputStream.close(); // 不用的话就把管子切断,节省内存// 以上写法其实都更倾向于读取一个字节数组}
}

六、FileOutputStream字节流写入文件

菜鸟教程
在这里插入图片描述
执行结果:
在这里插入图片描述

   @Testpublic void outputFile() throws IOException {FileOutputStream fileOutputStream = new FileOutputStream("file\\2.txt");// getBytes()作用:把字符串转换成字符数组byte[] bytes = "Hello World!".getBytes();
//        for(int i = 0; i < bytes.length; ++i){
//            System.out.print((char)bytes[i]);
//        }// 第一次执行上述命令后2.txt就会被创建出来, 删除方式:右击2.txt -> Delete -> OK -> 左下角Do Refactor// 把字符数组里的内容写入文件for(int i = 0; i < bytes.length; ++i){fileOutputStream.write(bytes[i]);}fileOutputStream.close();}

七、buff缓冲复制文件

文件输入输出流还有一些用途,比如说像:文件拷贝(文本文件(.txt)、媒体文件(.mp3、mp4、图片)均可)

1. 例一(无buff)

① 图片大的话可能会卡
② 此时是一个字节一个字节地从源文件读取,并且一个字节一个字节地写入到目标文件中。这种方式由于每次只处理一个字节,导致频繁地进行磁盘I/O操作,效率非常低。
在这里插入图片描述

@Testpublic void copyFileBase() throws IOException{FileInputStream fileInputStream = new FileInputStream("file\\1.jpg");FileOutputStream fileOutputStream = new FileOutputStream("file\\target.jpg");int by;while((by = fileInputStream.read()) != -1){fileOutputStream.write(by);}fileInputStream.close();fileOutputStream.close();}

2. 例二(有buff)

        代码使用了缓冲区(buffer),这是一个字节容器,用于在内存中暂存数据。缓冲区的大小在这里被设置为1024字节。这样,每次从源文件读取和写入目标文件时,都是按照缓冲区的大小来进行的,即每次操作都是1024字节。这大大减少了磁盘I/O操作的次数,因为每次操作都处理更多的数据,从而显著提高了文件复制的速度。
        当调用 fileInputStream.read(buff) 方法时,它会尝试填充整个缓冲区(最多1024字节),然后返回实际读取的字节数。这个字节数可能小于1024,比如在文件的最后部分。然后,fileOutputStream.write(buff, 0, by) 方法将这些字节写入目标文件。这个过程会一直重复,直到文件结束(即 read 方法返回-1)。
        可以理解为搬运箱子,之前是一个人搬一个箱子,突然来了个大力士,一次性可以搬10个箱子。
        总结来说,使用缓冲区是处理I/O操作时提高效率的常见做法,这在处理大文件时尤其重要。
在这里插入图片描述

 @Testpublic void copyFileBase2() throws IOException{FileInputStream fileInputStream = new FileInputStream("File\\1.jpg");FileOutputStream fileOutputStream = new FileOutputStream("File\\target2.jpg");// 缓冲区// 1024单位:字节byte[] buff = new byte[1024];int by;while((by=fileInputStream.read(buff)) != -1){fileOutputStream.write(buff, 0, by);}fileInputStream.close();fileOutputStream.close();}

八、buffered字节缓冲流和装饰设计模式

BufferedInputStream
① 之前用的是普通的字节流,然后手动创建缓冲区;现在直接用缓冲流,好处在于不需要自己手写缓冲区了。
② 装饰设计模式:把一个类当作一个函数的参数传进去
在这里插入图片描述
③ 这里默认的缓冲区大小是8192字节
在这里插入图片描述
在这里插入图片描述

@Testpublic void bufferFileBase() throws IOException{BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("file\\1.txt"));BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("file\\3.txt"));int by;while((by = bufferedInputStream.read()) != -1){bufferedOutputStream.write(by);}bufferedInputStream.close();bufferedOutputStream.close();}

九、FileReader和FileWriter,俩专门来搞txt文件的

在这里插入图片描述
② FileReader
     FileWriter
③ 用文件写学生管理系统,别再用FileInputStream和FileOutputStream了,应该用FileReader和FileWriter(它们针对于记事本这种输入输出设备文件)
在这里插入图片描述
在这里插入图片描述
        但是我们可以从源码发现,FileReader和FileWriter的原理其实还是FileInputStream和FileOutputStream,只不过它俩可以使代码看起来更简洁一点。

@Testpublic void fileReaderTest() throws IOException{FileReader fileReader = new FileReader("file\\1.txt");int ch;while((ch = fileReader.read()) != -1){// 可以把ln删掉System.out.print((char)ch);}fileReader.close();}@Testpublic void fileWriterTest() throws IOException{FileWriter fileWriter = new FileWriter("file\\4.txt");fileWriter.write("hello world!");fileWriter.close();}

十、BufferedReader和BufferedWriter

BufferedReader
BufferedWriter
① 进一步补充:用文件写学生管理系统,BufferedReader和BufferedWriter比FileReader和FileWriter速度快。
② 除此之外,BufferedWriter里有一个newLine()方法,可以根据不同的系统生成换行符(因为不同的系统换行符可能不同),所以更推荐用它去写入文件;BuffertedReader里有一个readLine()方法,可以按行读取字符
③ 但实际工作可能不太用这些

 @Testpublic void bufferedReaderTest() throws IOException{BufferedReader bufferedReader = new BufferedReader(new FileReader("file\\2.txt"));// 因为是字符流所以用String// 之前用int那种实际是有问题的String str;while ((str = bufferedReader.readLine()) != null){// 这个时候就可以加ln了System.out.println(str);}bufferedReader.close();}@Testpublic void bufferedWriterTest() throws IOException{BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("file\\5.txt"));bufferedWriter.write("hhhhhhhh");bufferedWriter.newLine();bufferedWriter.write("ffffffff");bufferedWriter.close();}

十一、一次性讲解剩余的N个流(扩展课)Java里那些极其骚的IO流

① 借助它们可以用字节流操作字符流。但是要注意文件得是文本文件(因为涉及到操作字符流)
转换流InputStreamReader
转换流OutputStreamWriter
② 对象输入输出流:把一个对象写入文件,传的参数是一个Object对象
在这里插入图片描述
③ 存取成员变量(成员数据)
在这里插入图片描述
④ 打印流:存一个小的东西作为字符串输出
在这里插入图片描述
⑤ 输入输出流:System.out.println
在上述PrintStream里
⑥ 控制台
在这里插入图片描述
⑦ 多线程管道流(写底层用的,平时用得不多):多线程用的,多线程管道输入。这个流需要一个线程控制它去读,一个线程控制它去写,跟打电话一样。
在这里插入图片描述
Channel就是一个信道,和管道有区别。它们都跟并发有关,性能很高。
在这里插入图片描述
在这里插入图片描述
⑩ 可以理解为装货卸货。货多的时候就算用缓冲流也依然很慢。ByteArrayOutputStream这个类在创建时会自动创建一个Byte[]类型的缓冲区,写入的时候先把所有东西丢到缓冲区,最后再把所有东西一次性扔到另一个文件里
在这里插入图片描述
⑪ 跟上面的类似,只不过这里存的是char
在这里插入图片描述
⑫ 网上那种多线程下载跟这个类似,它会把两个东西进行合并。例如创建2个文件input流时,它可以把2个流合并,变成一个流。
在这里插入图片描述
另一个构造方法用到泛型(写框架会用到),可以提供多个流进行合并
在这里插入图片描述
⑬ I/O流都是从前向后,先后顺序读取。要想从文件任意处进行读写操作,字符流和字节流都做不到,只有RandomAccessFile可以实现。它虽然在java.io包里,但是它不属于流
在这里插入图片描述
它可以用指针表明开始位置
在这里插入图片描述
或者直接用随机戳生成pos随机数
在这里插入图片描述

十二、Apache Common IO

apache公司自己写的io,可以帮助我们简化开发流程,非常实用
2.18jar包下载
2.18API文档
这里面有很多有意思的代码,例如:FileUtils。上节课手写的一些东西,这里几乎都有封装好可以直接拿来用的方法。
例子

1. 例一

在这里插入图片描述

@Testpublic void writeTest() throws IOException{File file = new File("file\\6.txt");if(!file.exists()){file.createNewFile();}FileUtils.writeLines(file, new ArrayList(Collections.singleton(("春风很柔,夏风很烈,秋风清爽,东风凛冽,你就是春夏秋冬的风"))), true);}

2. 例二(arrayList的妙用)

在这里插入图片描述
需要往文件里写很多东西时就可以用它
在这里插入图片描述
writeLines方法涉及到泛型

package com.practice.demo3;public class Student {private String name;private int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "name='" + name + '\'' +", age=" + age;}
}
@Testpublic void writeTest2() throws IOException{File file = new File("file\\7.txt");if(!file.exists()){file.createNewFile();}ArrayList<Student> arrayList = new ArrayList<>();// 第一个学生arrayList.add(new Student("Tom", 12));// 第二个学生arrayList.add(new Student("Jerry", 14));FileUtils.writeLines(file, arrayList, true);}

十三、补充

① File和IO Stream配合使用非常强
② 文件复制时也可以用这个类里的方法(这个类里有很多跟文件有关的方法,我们还可以用文件的方式去创建一个流甚至Channel),没必要使用上面说的字节流的方式
jdk文档
③ 复制文件时,我们可以使用字节流的方式,然后手动创建缓冲区;也可以用apache io 包里的方法;还可以用java.nio.file.Files类里的方法。
        综上,java中每种功能可能有多种实现方式,要依据当前的项目选择合适的实现方式。
④ c语言中的eof表示文件结束并已读取到最后一个字符。

十四、内容出处

java


http://www.mrgr.cn/news/79171.html

相关文章:

  • Edge SCDN深度解析,边缘安全加速的创新实践
  • Qwen 论文阅读记录
  • WIN11中安装Mamba常见问题解决方案
  • 图解大模型分布式训练:流水线并行
  • prometheusgrafana实现监控告警
  • 基于Springboot的实验室管理系统【附源码】
  • 工业—使用Flink处理Kafka中的数据_ChangeRecord2
  • PHP语法学习(第三天)
  • 深入浅出:Go语言中map的工作原理详解
  • Redis设计与实现读书笔记
  • 万字长文解读深度学习——dVAE(DALL·E的核心部件)
  • centos 手动安装libcurl4-openssl-dev库
  • (12)时间序列预测之MICN(CNN)
  • 基于ZooKeeper搭建Hadoop高可用集群
  • 深入浅出:Python 编程语言的学习之路
  • 工业—使用Flink处理Kafka中的数据_ChangeRecord1
  • OpenVas安装步骤及报错问题
  • vscode远程连接ssh
  • Nginx 缓存 DNS 解析问题
  • THREE.js 入门(一)xyz坐标系
  • 深入浅出:php-学习入门全攻略
  • Docker 安装系列
  • git管理Unity项目的正确方式
  • python更新程序并部署服务器服务
  • 字符串函数和内存函数
  • C++ packaged_task