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

节点流和处理流基本使用

文章目录

  • 1. 基本介绍
  • 2. 节点流和处理流一览图
  • 3. 节点流和处理流的区别和联系
  • 4. 处理流的功能主要体现在以下两个方面
  • 5. 处理流 BufferedReader 和 BufferedWriter
  • 6. 处理流-BufferedInputStream 和 BufferedOutputStream
  • 7. 对象流-ObjectInputStream 和 ObjectOutputStream
  • 8. 对象流介绍
  • 9. 标准输入输出流
  • 10. 转换流-InputStreamReader 和 OutputStreamWriter
  • 11. 打印流-PrintStream和PrintWriter

1. 基本介绍

  1. 节点流可以从一个特定的数据源读写数据,如: FileReaderFileWriter

在这里插入图片描述

  1. 处理流(也叫包装流)是“连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如:BufferedReaderBufferedWriter

在这里插入图片描述

2. 节点流和处理流一览图

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 节点流和处理流的区别和联系

  1. 节点流是底层流/低级流,直接跟数据源相接
  2. 处理流(包装流)包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出
  3. 处理流(包装流)对节点流进行包装,使用了修饰器设计模式,不会直接与数据
    源相连【模拟修饰器设计模式】

4. 处理流的功能主要体现在以下两个方面

  1. 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
  2. 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使
    用更加灵活方便

5. 处理流 BufferedReader 和 BufferedWriter

  • BufferedReaderBufferedWriter 属于字符流,是按照字符来读取数据的关闭时处理流,只需要关闭外层流即可
  • 案例1:使用BufferedReader读取文本文件,并显示在控制台
public class BufferedReader_ {public static void main(String[] args) throws Exception {String filePath = "e:\\hello.txt";//创建bufferedReaderBufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));//读取String line; //按行读取, 效率高//说明//1. bufferedReader.readLine() 是按行读取文件//2. 当返回null 时,表示文件读取完毕while ((line = bufferedReader.readLine()) != null) {System.out.println(line);}//关闭流, 这里注意,只需要关闭 BufferedReader ,因为底层会自动的去关闭 节点流//FileReader。/* 源码public void close() throws IOException {synchronized (lock) {if (in == null)return;try {in.close();//in 就是我们传入的 new FileReader(filePath), 关闭了.} finally {in = null;cb = null;}}}*/bufferedReader.close();}
}
  • 运行结果:
hello,你好呀。
  • 案例2:使用BufferedWriter将 ”hello,兮动人”,写入到文件中
public class BufferedWriter_ {public static void main(String[] args) throws IOException {String filePath = "e:\\ok.txt";//创建BufferedWriter//说明://1. new FileWriter(filePath, true) 表示以追加的方式写入//2. new FileWriter(filePath) , 表示以覆盖的方式写入BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));bufferedWriter.write("hello, 兮动人!");bufferedWriter.newLine();//插入一个和系统相关的换行bufferedWriter.write("hello2, 兮动人!");bufferedWriter.newLine();bufferedWriter.write("hello3, 兮动人!");bufferedWriter.newLine();//说明:关闭外层流即可 , 传入的 new FileWriter(filePath) ,会在底层关闭bufferedWriter.close();}
}
  • 运行后:
    在这里插入图片描述

  • 案例3:综合使用BufferedReader和BufferedWriter完成文本文件拷贝,注
    意文件编码。

public class BufferedCopy_ {public static void main(String[] args) {//1. BufferedReader 和 BufferedWriter 是按照字符操作//2. 不要去操作 二进制文件[声音,视频,doc, pdf ], 可能造成文件损坏//BufferedInputStream//BufferedOutputStreamString srcFilePath = "e:\\hello.txt";String destFilePath = "e:\\hello2.txt";BufferedReader br = null;BufferedWriter bw = null;String line;try {br = new BufferedReader(new FileReader(srcFilePath));bw = new BufferedWriter(new FileWriter(destFilePath));//说明: readLine 读取一行内容,但是没有换行while ((line = br.readLine()) != null) {//每读取一行,就写入bw.write(line);//插入一个换行bw.newLine();}System.out.println("拷贝完毕...");} catch (IOException e) {e.printStackTrace();} finally {//关闭流try {if(br != null) {br.close();}if(bw != null) {bw.close();}} catch (IOException e) {e.printStackTrace();}}}
}

6. 处理流-BufferedInputStream 和 BufferedOutputStream

  • 介绍 BufferedInputStream

在这里插入图片描述
在这里插入图片描述

  • 介绍 BufferedOutputStream

在这里插入图片描述

在这里插入图片描述

  • 案例:完成图片/音乐的拷贝(要求使用Buffered…流)

这块也可以拷贝图片、音乐和文本等

public class BufferedCopy02 {public static void main(String[] args) {String srcFilePath = "e:\\imgs\\xdr.png";String destFilePath = "e:\\imgs\\xdr2.png";//创建BufferedOutputStream对象BufferedInputStream对象BufferedInputStream bis = null;BufferedOutputStream bos = null;try {//因为 FileInputStream  是 InputStream 子类bis = new BufferedInputStream(new FileInputStream(srcFilePath));bos = new BufferedOutputStream(new FileOutputStream(destFilePath));//循环的读取文件,并写入到 destFilePathbyte[] buff = new byte[1024];int readLen = 0;//当返回 -1 时,就表示文件读取完毕while ((readLen = bis.read(buff)) != -1) {bos.write(buff, 0, readLen);}System.out.println("文件拷贝完毕~~~");} catch (IOException e) {e.printStackTrace();} finally {//关闭流 , 关闭外层的处理流即可,底层会去关闭节点流try {if(bis != null) {bis.close();}if(bos != null) {bos.close();}} catch (IOException e) {e.printStackTrace();}}}
}

在这里插入图片描述

7. 对象流-ObjectInputStream 和 ObjectOutputStream

看一个需求

  1. int num = 100这个int数据保存到文件中,注意不是100数字,而是 int 100,并且,能够从文件中直接恢复 int 100
  2. Dog dog = new Dog("小黄", 3)这个dog对象保存到文件中,并且能够从文件恢复
  3. 上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化操作

序列化和反序列化

  1. 序列化就是在保存数据时,保存数据的值数据类型
  2. 反序列化就是在恢复数据时,恢复数据的值数据类型
  3. 如果需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
Serializable //这是一个标记接口,没有方法
Externalizable //该接口有方法需要实现,因此我们一般实现上面的Serializable接口

在这里插入图片描述

8. 对象流介绍

功能:提供了对基本类型或对象类型的序列化和反序列化的方法

  • ObjectOutputStream 提供 序列化 功能

在这里插入图片描述

  • ObjectInputStream 提供 反序列化 功能

在这里插入图片描述

  • 案例1:使用ObjectOutputStream序列化基本数据类型和一个Dog对象(name,age),并保存到 data.dat 文件中
public class ObjectOutStream_ {public static void main(String[] args) throws Exception {//序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存String filePath = "e:\\data.dat";ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));//序列化数据到 e:\data.datoos.writeInt(100);// int -> Integer (实现了 Serializable)oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)oos.writeChar('a');// char -> Character (实现了 Serializable)oos.writeDouble(9.5);// double -> Double (实现了 Serializable)oos.writeUTF("兮动人");//String//保存一个dog对象oos.writeObject(new Dog("小狗", 10, "中国", "白色"));oos.close();System.out.println("数据保存完毕(序列化形式)");}
}class Dog implements Serializable {private String name;private int age;private String country;private String color;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;}public String getCountry() {return country;}public void setCountry(String country) {this.country = country;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public Dog(String name, int age, String country, String color) {this.name = name;this.age = age;this.country = country;this.color = color;}
}
  • 案例2:使用ObjectlnputStream读取data.dat并反序列化恢复数据
public class ObjectInputStream_ {public static void main(String[] args) throws ClassNotFoundException, IOException {//指定反序列化的文件String filePath = "e:\\data.dat";ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));// 读取//1. 读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致//2. 否则会出现异常System.out.println(ois.readInt());System.out.println(ois.readBoolean());System.out.println(ois.readChar());System.out.println(ois.readDouble());System.out.println(ois.readUTF());//dog 的编译类型是 Object , dog 的运行类型是 DogObject dog = ois.readObject();System.out.println("运行类型=" + dog.getClass());System.out.println("dog信息=" + dog);//底层 Object -> Dog// 这里是特别重要的细节://1. 如果我们希望调用Dog的方法, 需要向下转型//2. 需要我们将Dog类的定义,放在到可以引用的位置Dog dog2 = (Dog)dog;System.out.println(dog2.getName());//关闭流, 关闭外层流即可,底层会关闭 FileInputStream 流ois.close();}
}

在这里插入图片描述

注意事项和细节说明
1)读写顺序要一致
2)要求序列化或反序列化对象,需要实现Serializable
3)序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
4)序列化对象时,默认将里面所有属性都进行序列化,但除了statictransient修饰的成员
5)序列化对象时,要求里面属性的类型也需要实现序列化接口
6)序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化

9. 标准输入输出流

public class InputAndOutput {public static void main(String[] args) {//System 类 的 public final static InputStream in = null;// System.in 编译类型   InputStream// System.in 运行类型   BufferedInputStream// 表示的是标准输入 键盘System.out.println(System.in.getClass());//1. System.out public final static PrintStream out = null;//2. 编译类型 PrintStream//3. 运行类型 PrintStream//4. 表示标准输出 显示器System.out.println(System.out.getClass());System.out.println("hello, 兮动人~");Scanner scanner = new Scanner(System.in);System.out.println("输入内容");String next = scanner.next();System.out.println("next=" + next);}
}

10. 转换流-InputStreamReader 和 OutputStreamWriter

  • 先看一个文件乱码问题,引出学习转换流必要性
public class CodeQuestion {public static void main(String[] args) throws IOException {//读取e:\\a.txt 文件到程序//思路//1.  创建字符输入流 BufferedReader [处理流]//2. 使用 BufferedReader 对象读取a.txt//3. 默认情况下,读取文件是按照 utf-8 编码String filePath = "e:\\a.txt";BufferedReader br = new BufferedReader(new FileReader(filePath));String s = br.readLine();System.out.println("读取到的内容: " + s);br.close();}
}

在这里插入图片描述

  • 如果把 a.txt 换成 GBK 格式,读出来的内容就会乱码

ANSI并不是某一种特定的字符编码,而是在不同的系统中,ANSI表示不同的编码。具体是要取决于操作系统,如果是中文操作系统ANSI表的是 GBK 编码格式。

在这里插入图片描述
在这里插入图片描述

  1. InputStreamReader:Reader的子类,可以将InputStream(字节流)包
    装成(转换)Reader(字符流)
  2. OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)
    包装成Writer(字符流)
  3. 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文
    问题,所以建议将字节流转换成字符流
  4. 可以在使用时指定编码格式(比如utf-8,gbk,gb2312,1SO8859-1等)

在这里插入图片描述
在这里插入图片描述

  • 应用案例
  1. 编程将字节流FilelnputStream包装成(转换成)字符流InputStreamReader,对文件进行读取(按照utf-8/gbk格式),进而在包装成BufferedReader
/*** 演示使用 InputStreamReader 转换流解决中文乱码问题* 将字节流 FileInputStream 转成字符流  InputStreamReader, 指定编码 gbk/utf-8*/
public class InputStreamReader_ {public static void main(String[] args) throws IOException {String filePath = "e:\\a.txt";//解读//1. 把 FileInputStream 转成 InputStreamReader//2. 指定编码 gbk//InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");//3. 把 InputStreamReader 传入 BufferedReader//BufferedReader br = new BufferedReader(isr);//将2 和 3 合在一起BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath), "gbk"));//4. 读取String s = br.readLine();System.out.println("读取内容=" + s);//5. 关闭外层流br.close();}}

在这里插入图片描述

  1. 编程将字节流FileOutputStream包装成(转换成)字符流OutputStreamWriter,对文件进行写入(按照gbk格式,可以指定其他,比如utf-8
public class OutputStreamWriter_ {public static void main(String[] args) throws IOException {String filePath = "e:\\xdr.txt";String charSet = "utf-8";OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet);osw.write("hi, 兮动人");osw.close();System.out.println("按照 " + charSet + " 保存文件成功~");}
}

11. 打印流-PrintStream和PrintWriter

在这里插入图片描述
在这里插入图片描述

  1. 演示PrintStream (字节打印流/输出流)
public class PrintStream_ {public static void main(String[] args) throws IOException {PrintStream out = System.out;//在默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器/*public void print(String s) {if (s == null) {s = "null";}write(s);}*/out.print("john, hello");//因为print底层使用的是write , 所以我们可以直接调用write进行打印/输出out.write("兮动人,你好".getBytes());out.close();//我们可以去修改打印流输出的位置/设备//1. 输出修改成到 "e:\\f1.txt"//2. "hello, 兮动人~" 就会输出到 e:\f1.txt//3. public static void setOut(PrintStream out) {//        checkIO();//        setOut0(out); // native 方法,修改了out//   }System.setOut(new PrintStream("e:\\f1.txt"));System.out.println("hello, 兮动人~");}
}
  1. 演示 PrintWriter 使用方式
public class PrintWriter_ {public static void main(String[] args) throws IOException {//PrintWriter printWriter = new PrintWriter(System.out);PrintWriter printWriter = new PrintWriter(new FileWriter("e:\\f2.txt"));printWriter.print("hi, 云兮动人~~~~");printWriter.close();//flush + 关闭流, 才会将数据写入到文件..}
}

相关文章:

  • 探索 Model Context Protocol (MCP):它如何影响 AI 的表现?
  • Go语言--语法基础4--基本数据类型--浮点数类型
  • Cherry Studio配置MCP服务全流程解析
  • Unity3D仿星露谷物语开发37之浇水动画
  • 色谱图QCPColorMap
  • React Router V7使用详解
  • 用于手部康复设备的TinyML语音分类嵌入式人工智能模块
  • OpenCV 对图像进行阈值处理 cv2.threshold
  • 【Rust 精进之路之第11篇-借用·实践】切片 (Slices):安全、高效地引用集合的一部分
  • Opencv图像处理:轮廓检测、轮廓近似、绘制外接圆外接矩形
  • 嵌入式学习——opencv图像库编程
  • puzzle(0531)脑力航迹
  • 33-公交车司机管理系统
  • [ABAQUS有限元分析] 1.单个零件静力学分析
  • Nginx在微服务架构项目(Spring Cloud)中的强大作用
  • 30元一公斤的樱桃甜不甜
  • 《Operating System Concepts》阅读笔记:p748-p748
  • MySQL:9.表的内连和外连
  • 山东大学创新项目实训开发日志(19)之前端知识深度学习
  • 2-6-1-1 QNX编程入门之进程和线程(八)
  • 官方披露:WinRAR安全漏洞可绕过安全警告,执行恶意软件
  • 美国海关新规致跨境包裹延误,DHL暂停超800美元对美个人货运
  • 多元布局、抱团取暖……上海虹口区召开外向型企业圆桌会议
  • 对话地铁读书人|来自法学副教授的科普:读书日也是版权日
  • 全球建筑瞭望|与自然共呼吸的溪谷石舍与海边公共空间
  • 习近平会见柬埔寨人民党主席、参议院主席洪森