04-IO资源的处理、缓冲流、转换流、对象流、打印流、Properties属性集、装饰模式
1、IO资源的处理
-
JDK1.7前的处理方式
-
// JDK1.7以前处理IO流异常 FileWriter fw1 = null; try { fw1 = new FileWriter("study_day11\\abc\\bos.txt"); } catch (IOException e) { System.out.println("处理创建流异常"); } finally { if (fw1 !=null){ try { fw1.close(); } catch (IOException e) { System.out.println("处理关闭异常"); } } }
-
-
JDK1.7之后的处理方式
-
JDK7增加了try-with-resource语句来处理资源,该语句确保了每个资源在语句结束的时候关闭
-
try (FileWriter fw2 = new FileWriter("study_day11\\abc\\bos.txt")) { fw2.write("46"); } catch (IOException e) { System.out.println("处理关闭异常"); }
-
2、缓冲流
2.1、缓冲流介绍
- 按照数据类型分类
- 字节缓冲流
- BufferedInputStream, BufferedOutputStream
- 字符缓冲流
- BufferedReader, BufferedWriter
- 字节缓冲流
- 缓冲流的好处
- 缓冲流内置的默认8K大小的缓冲区数组,减少系统IO次数,从而提高读写的效率
2.2、字节缓冲流
2.2.1、体系结构
2.2.2、字节缓冲流API
- public BufferedInputStream(InputStream in)
- 把基本的字节输入流包装成一个字节输入缓冲流,从而提高字节输入流读数据的性能
- public BufferedOutputStream(OutputStream out)
- 把基本的字节输出流包装成一个字节输出缓冲流,从而提高写数据的性能
2.2.3、字节输出缓冲流
- public BufferedOutputStream(OutputStream out)
- 把基本的字节输出流包装成一个字节输出缓冲流,从而提高写数据的性能
2.2.4、缓冲流的规律
- 以Buffered开头
- 后缀就是继承的父类
2.2.5、字节输入缓冲流
-
public BufferedInputStream(InputStream in)
- 把基本的字节输入流包装成一个字节输入缓冲流,从而提高字节输入流读数据的性能
-
demo
-
// 1.创建缓冲字节输入流 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("study_day11\\abc\\bos.txt")); // 2.读数据 int b; while ((b = bis.read()) != -1) { System.out.println((char) b); } // 3.关闭 bis.close();
-
2.2.6、案例(字节流四种复制文件)
-
基本流读取一个字节
-
// 基本流读写一个字节 public static void test01() throws IOException { // 创建输入流 FileInputStream fis = new FileInputStream("D:/MyFileTest/高清无码.flv"); // 创建输出流 FileOutputStream fos = new FileOutputStream("D:/MyFileTest/高清无码1.flv"); // 循环读写 int b; // 保存读取的数据 while ((b = fis.read()) != -1) { fos.write(b); } // 关闭流 fos.close(); fis.close(); }
-
-
基本流读取一个字节数组
-
// 基本流读写一个字节数组 public static void test02() throws IOException { // 创建输入流 FileInputStream fis = new FileInputStream("D:/MyFileTest/高清无码.flv"); // 创建输出流 FileOutputStream fos = new FileOutputStream("D:/MyFileTest/高清无码2.flv"); // 循环读写 byte[] buf = new byte[1024*8]; // 保存读取的数据 int len; // 保存读取的数量 while ((len = fis.read(buf)) != -1) { fos.write(buf, 0, len); } // 关闭流 fos.close(); fis.close(); }
-
-
缓冲流读取一个字节
-
// 缓冲流读写一个字节 public static void test03() throws IOException { // 创建输入流 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/MyFileTest/高清无码.flv")); // 创建输出流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/MyFileTest/高清无码3.flv")); // 循环读写 int b; // 保存读取的数据 while ((b = bis.read()) != -1) { bos.write(b); } // 关闭流 bos.close(); bis.close(); }
-
-
缓冲流读取一个字节数组
-
// 缓冲流读写一个字节数组 public static void test04() throws IOException { // 创建输入流 BufferedInputStream bis = new BufferedInputStream(new FileInputStream("D:/MyFileTest/高清无码.flv")); // 创建输出流 BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("D:/MyFileTest/高清无码4.flv")); // 循环读写 byte[] buf = new byte[1024 * 8]; // 8192 int len; while ((len = bis.read(buf)) != -1) { bos.write(buf, 0, len); } // 关闭流 bos.close(); bis.close(); }
-
2.3、字符缓冲流
2.3.1、字符输出缓冲流
- BufferedWriter
- 方法
- public BufferedWriter(Writer r)
- 把基本的字符输出流包装成一个字符输出缓冲流,从而提高字符输出流写数据的性能
- public BufferedWriter(Writer r)
- 字符输出缓冲流新增功能
- public String newLine()
- 换行
- public String newLine()
- 方法
2.3.2、字符输入缓冲流
- BufferedReader
- 方法
- public BufferedReader(Reader r)
- 把基本的字符输入流包装成一个字符输入缓冲流,从而提高字符输入缓冲流读数据的性能
- 字符输入缓冲流新增功能
- public String readLine()
- 读取一行数据返回,如果读取没有完毕,无行可读则返回null
- public String readLine()
- 方法
2.3.3、字符缓冲流为什么提高了操作数据的性能
- 字符缓冲流自带8K缓冲区
- 可以提高原始字符流读写数据的性能
3、转换流
3.1、字符集和字符编码的概念
- 字符集
- ASCII字符集
- ISO-8859-1字符集
- GBxxx字符集
- Unicode字符集
- 字符编码
- 将字符转成n进制,称为编码
- 如将字符转成二进制
- 将n进制转成字符,称为解码
- 如将二进制转换成文字
- 将字符转成n进制,称为编码
3.2、字符流读不同编码的文件乱码
- 乱码原因
- 文件保存到文件中的编码和读取文字时使用的编码不一致
- 乱码解决方案
- 保证存储和取出时编码一致即可
3.3、转换流的使用
-
InputStreamReader
-
可以指定编码读取数据
-
demo
-
InputStreamReader isr = new InputStreamReader(new FileInputStream("study_day11\\abc\\china_gbk.txt"),"GBK"); int ch; while ((ch = isr.read()) != -1){ System.out.println((char) ch); } isr.close();
-
-
-
OutputStreamWriter
-
可以指定编码写数据
-
方法
- OutputStreamWriter(OutputStream out)
- 使用默认编码写数据
- OutputStreamWriter(OutputStream out, String charsetName)
- 使用指定编码写数据
- OutputStreamWriter(OutputStream out)
-
demo
-
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("study_day11\\abc\\hello_gbk.txt"), "GBK"); osw.write("你好"); osw.close();
-
-
3.4、操作字符的时候如何选择流
- 基本流(FileReader/FileWriter)
- 如果不需要修改编码就使用基本流,使用更简单
- 转换流(InputStreamReader/OutputStreamWriter)
- 如果需要修改编码就使用转换流
3.5、案例(文件转码)
-
步骤
- 使用GBK编码读取文件内容
- 使用UTF-8编码写字符数据到文件
- 循环读写
-
代码示例
-
package Day11.demo09转换文件编码_重点; import java.io.*; /* 目标:将GBK编码的文本文件,转换为UTF-8编码的文本文件 讲解: 步骤: 1.使用GBK编码读取文件内容 2.使用UTF-8编码写字符数据到文件 3.循环读写 */ public class Demo09 { public static void main(String[] args) throws IOException { // 1.使用GBK编码读取文件内容 InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream("DarkHorseEmployment\\src\\Day11\\demo09转换文件编码_重点\\gbk.txt"), "GBK"); // 2.使用UTF-8编码写字符数据到文件 OutputStreamWriter outputStreamWriter = new OutputStreamWriter(new FileOutputStream("DarkHorseEmployment\\src\\Day11\\demo09转换文件编码_重点\\utf-8.txt"), "utf-8"); // 3.循环读写 int len; while ((len = inputStreamReader.read()) != -1) { System.out.println("len = " + len); System.out.println("(char) len = " + (char) len); outputStreamWriter.write((char) len); } System.out.println("写入成功!"); // 4.关闭文件 outputStreamWriter.close(); inputStreamReader.close(); } }
-
4、对象流
4.1、对象操作流分类
-
ObjectOutputStream
-
对象输出流
-
ObjectOutputStream oos = new ObjectOutputStream(基本流); oos.writeObject(对象);
-
-
ObjectInputStream
-
对象输入流
-
ObjectInputStream ois = new ObjectInputStream(基本流); ois.readObject();
-
4.2、对象流的使用
- 输出流
- ObjectOutputStream(OutputStream out)
- 对象输出流,把对象以字节的形式写道本地文件
- public void writeObject(Object obj)
- 写一个对象到文件中
- ObjectOutputStream(OutputStream out)
- 输入流
- ObjectInputStream(InputStream in)
- 对象输入流,把写到本地文件中的对象读取到内存当中
- public Object readObject()
- 读取文件中的对象数据到文件中
- ObjectInputStream(InputStream in)
4.3、对象流细节
- 使用对象输出流将对象保存到文件时会出现NotSerializableExxception异常
- 解决
- 需要让类实现Serializable接口
4.4、案例(用对象流读写多个对象)
-
步骤
- 把若干学生对象,保存到集合中
- 把集合序列化
- 反序列化读取时,只需要读取一次,转换为集合类型
- 遍历集合,打印所有的学生信息
-
demo
-
Student类
-
package Day11.demo10ObjectOutputStream对象输出流; import java.io.Serializable; public class Student implements Serializable { private String name; private int age; private char sex; public Student(String name, int age, char sex) { this.name = name; this.age = age; this.sex = sex; } public Student() { } 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 char getSex() { return sex; } public void setSex(char sex) { this.sex = sex; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + ", sex=" + sex + '}'; } }
-
-
Demo类
-
public class Demo10 { public static void main(String[] args) throws IOException { ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("F:\\GoodGoodStudy\\DarkHorseEmployment\\src\\Day11\\demo10ObjectOutputStream对象输出流\\students.txt")); objectOutputStream.writeObject(new Student("梁朝伟", 44, '男')); objectOutputStream.writeObject(new Student("黎明", 49, '男')); objectOutputStream.writeObject(new Student("刘德华", 46, '男')); objectOutputStream.writeObject(new Student("郭富城", 44, '男')); objectOutputStream.writeObject(new Student("刘亦菲", 18, '女')); objectOutputStream.close(); } } public class Demo11 {
public static void main(String[] args) throws IOException, ClassNotFoundException {ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("DarkHorseEmployment\\src\\Day11\\demo10ObjectOutputStream对象输出流\\students.txt")); ArrayList<Student> people = new ArrayList<>(); while (true) { try { Student o = (Student) objectInputStream.readObject(); people.add(o); }catch (EOFException e) { break; } } System.out.println("people = " + people); } }
-
-
5、打印流
- 作用
- 打印流可以实现方便、高效的打印数据到文件中去
- 打印流构造器
- PrintStream(File file)
- 创建PrintStream,指定打印的目的地
- PrintStream(String fileName)
- 创建PrintStream,指定打印的目的地
- PrintStream(OutputStream out)
- 创建PrintStream,指定打印的目的地
- PrintStream(File file)
- 方法
- print(Xxx x)
- 打印数据,不换行
- println(Xxx x)
- 打印数据,换行
- print(Xxx x)
6、Properties属性集
6.1、Properties体系结构
6.2、Properties作为集合使用
- Properties实现了Map接口,就是一个双列集合,可以存储键值对
- PS:Properties集合的键值对都是字符串类型
- Properties可以结合流进行操作,可以把集合中的数据保存到流中,也可以从流中来加载数据
6.3、Properties作为集合的特有方法
- Object setProperty(String key, String value)
- 添加键和值,键和值都是String类型
- String getProperty(String key)
- 通过键获取值
- Set
stringPropertyNames() - 获取所有的键
6.4、Properties和IO流结合的方法
- 方法
- void load(Reader reader)
- 从输入字符流读取属性列表(键和值)
- void store(Writer writer, String comments)
- 将Properties中的键和值写入输出字符流中
- void load(InputStream inStream)
- 从输入字节流读取属性列表(键和元素对)
- void store(OutputStream out, String comments)
- 将Properties中的键和值写入输出字节流中
- void load(Reader reader)
6.5、使用Properties的load方法加载文件中配置信息代码示例
-
public static void testLoad() throws IOException { Properties pp = new Properties(); System.out.println("加载前: " + pp); pp.load(new FileReader("study_day11\\abc\\pp.properties")); System.out.println("加载后: " + pp); }
7、装饰模式
- 装饰设计模式的作用
- 可以增强原本的类和扩展类的功能
- 装饰设计模式有三个角色
- 共同的接口
- 原对象
- 装饰对象
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了