• IO流的讲解(3)


    目录

    处理流-BufferedInputStream和BufferedOutputStream

    BufferedInputStream介绍

    BufferedOutputStream介绍

    处理流的应用实例

    对象流

    序列化和反序列化

    基本介绍

    应用案例1

    应用案例2

    序列化和反序列化的注意事项和细节说明

    标准输入输出流

    转换流

    乱码问题


    处理流-BufferedInputStream和BufferedOutputStream

    在Java中,BufferedInputStream和BufferedOutputStream是两个非常重要的类,它们的主要作用是提高I/O性能。接下来看看

    BufferedInputStream介绍

    BufferedInputStream类是为了提高读取效率而设计的。它在内部维护了一个缓冲区,每次从输入流中读取数据时,它会将数据读入到缓冲区中。然后,它将返回缓冲区中的数据而不是每次直接从输入流中读取数据。这可以大大减少访问底层输入流的次数,从而提高读取效率。

    BufferedOutputStream介绍

    BufferedOutputStream类也是为了提高写入效率而设计的。它在内部维护了一个缓冲区,每次进行写入操作时,它会将数据先写入到缓冲区中,然后再一次性将缓冲区中的数据写出到底层输出流中。这样可以减少写入操作对底层输出流的访问次数,从而提高写入效率。

    相比于直接使用底层输入输出流,使用BufferedInputStream和BufferedOutputStream类能够提高I/O操作的效率和性能。

    处理流的应用实例

    代码演示:

    和之前的读取文件一样,定义要读取文件的路径和写入到哪个文件,这里我们拷贝的是二进制文件,也就是音频等文件

    1. package com.outputstream_;
    2. import com.reader_.BufferedReader_;
    3. import com.sun.xml.internal.org.jvnet.mimepull.MIMEConfig;
    4. import java.io.*;
    5. /**
    6. * 演示使用BufferedOutputStream 和 BufferedInputStream使用
    7. * 使用他们,可以完成二进制文件拷贝.
    8. * 思考:字节流可以操作二进制文件,可以操作文本文件吗?当然可以
    9. */
    10. public class BufferedCopy02 {
    11. public static void main(String[] args) {
    12. // String srcFilePath = "e:\\Koala.jpg";
    13. String srcFilePath = "e:\\asd.java";
    14. String destFilePath = "e:\\a1.java";
    15. //创建BufferedOutputStream对象BufferedInputStream对象
    16. BufferedInputStream bis = null;
    17. BufferedOutputStream bos = null;
    18. try {
    19. //因为 FileInputStream 是 InputStream 子类
    20. bis = new BufferedInputStream(new FileInputStream(srcFilePath));
    21. bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
    22. //循环的读取文件,并写入到 destFilePath
    23. byte[] buff = new byte[1024];
    24. int readLen = 0;
    25. //当返回 -1 时,就表示文件读取完毕
    26. while ((readLen = bis.read(buff)) != -1) {
    27. bos.write(buff, 0, readLen);
    28. }
    29. System.out.println("文件拷贝完毕~~~");
    30. } catch (IOException e) {
    31. e.printStackTrace();
    32. } finally {
    33. //关闭流 , 关闭外层的处理流即可,底层会去关闭节点流
    34. try {
    35. if (bis != null) {
    36. bis.close();
    37. }
    38. if (bos != null) {
    39. bos.close();
    40. }
    41. } catch (IOException e) {
    42. e.printStackTrace();
    43. }
    44. }
    45. }
    46. }

    对象流

    对象流-ObjectInputStream和ObjectOutputStream

    序列化和反序列化

    1.序列化就是在保存数据时,保存数据的值和数据类型

    2.反序列化就是在恢复数据时,恢复数据的值和数据类型

    3.需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之

    -Serializable// 这是一个标记接口,没有方法

    Externalizable // 该接口有方法需要实现,因此我们一般实现上面的 Serializable接口

    基本介绍

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

    2.ObjectOutputStream 提供 序列化功能

    3.ObjectInputStream 提供 反序列化功能

    应用案例1

    完成文件的序列化

    代码演示:

    如果需要序列化某个类的对象,实现 Serializable接口,在序列化对象时,默认将里面所有属性都进行序列化,但除了statictransient修饰的成员,序列化对象时,要求里面属性的类型也需要实现序列化接口,然后使用ObjectOutputStream序列化文件

    1. package com.outputstream_;
    2. import java.io.FileNotFoundException;
    3. import java.io.FileOutputStream;
    4. import java.io.ObjectOutputStream;
    5. /**
    6. * 演示ObjectOutputStream的使用, 完成数据的序列化
    7. */
    8. public class ObjectOutStream_ {
    9. public static void main(String[] args) throws Exception {
    10. //序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
    11. String filePath = "e:\\data.dat";
    12. ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
    13. //序列化数据到 e:\data.dat
    14. oos.writeInt(100);// int -> Integer (实现了 Serializable)
    15. oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
    16. oos.writeChar('a');// char -> Character (实现了 Serializable)
    17. oos.writeDouble(9.5);// double -> Double (实现了 Serializable)
    18. oos.writeUTF("你好");//String
    19. //保存一个dog对象
    20. oos.writeObject(new Dog("旺财", 10, "日本", "白色"));
    21. oos.close();
    22. System.out.println("数据保存完毕(序列化形式)");
    23. }
    24. }
    25. package com.outputstream_;
    26. import java.io.Serializable;
    27. //如果需要序列化某个类的对象,实现 Serializable
    28. public class Dog implements Serializable {
    29. private String name;
    30. private int age;
    31. //序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
    32. private static String nation;
    33. private transient String color;
    34. //序列化对象时,要求里面属性的类型也需要实现序列化接口
    35. private Master master = new Master();
    36. //serialVersionUID 序列化的版本号,可以提高兼容性
    37. private static final long serialVersionUID = 1L;
    38. public Dog(String name, int age, String nation, String color) {
    39. this.name = name;
    40. this.age = age;
    41. this.color = color;
    42. this.nation = nation;
    43. }
    44. @Override
    45. public String toString() {
    46. return "Dog{" +
    47. "name='" + name + '\'' +
    48. ", age=" + age +
    49. ", color='" + color + '\'' +
    50. '}' + nation + " " +master;
    51. }
    52. public String getName() {
    53. return name;
    54. }
    55. public void setName(String name) {
    56. this.name = name;
    57. }
    58. public int getAge() {
    59. return age;
    60. }
    61. public void setAge(int age) {
    62. this.age = age;
    63. }
    64. }

    应用案例2

    反序列化

    代码演示:

    在反序列化的时候,要注意,反序列化的时候,读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致,否则会有异常

    1. package com.inputstream_;
    2. import com.outputstream_.Dog;
    3. import java.io.FileInputStream;
    4. import java.io.IOException;
    5. import java.io.ObjectInputStream;
    6. public class ObjectInputStream_ {
    7. public static void main(String[] args) throws IOException, ClassNotFoundException {
    8. //指定反序列化的文件
    9. String filePath = "e:\\data.dat";
    10. ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
    11. //读取
    12. //解读
    13. //1. 读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致
    14. //2. 否则会出现异常
    15. System.out.println(ois.readInt());
    16. System.out.println(ois.readBoolean());
    17. System.out.println(ois.readChar());
    18. System.out.println(ois.readDouble());
    19. System.out.println(ois.readUTF());
    20. //dog 的编译类型是 Object , dog 的运行类型是 Dog
    21. Object dog = ois.readObject();
    22. System.out.println("运行类型=" + dog.getClass());
    23. System.out.println("dog信息=" + dog);//底层 Object -> Dog
    24. //这里是特别重要的细节:
    25. //1. 如果我们希望调用Dog的方法, 需要向下转型
    26. //2. 需要我们将Dog类的定义,放在到可以引用的位置
    27. Dog dog2 = (Dog)dog;
    28. System.out.println(dog2.getName()); //旺财..
    29. //关闭流, 关闭外层流即可,底层会关闭 FileInputStream 流
    30. ois.close();
    31. }
    32. }
    33. package com.outputstream_;
    34. import java.io.Serializable;
    35. //如果需要序列化某个类的对象,实现 Serializable
    36. public class Dog implements Serializable {
    37. private String name;
    38. private int age;
    39. //序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
    40. private static String nation;
    41. private transient String color;
    42. //序列化对象时,要求里面属性的类型也需要实现序列化接口
    43. private Master master = new Master();
    44. //serialVersionUID 序列化的版本号,可以提高兼容性
    45. private static final long serialVersionUID = 1L;
    46. public Dog(String name, int age, String nation, String color) {
    47. this.name = name;
    48. this.age = age;
    49. this.color = color;
    50. this.nation = nation;
    51. }
    52. @Override
    53. public String toString() {
    54. return "Dog{" +
    55. "name='" + name + '\'' +
    56. ", age=" + age +
    57. ", color='" + color + '\'' +
    58. '}' + nation + " " +master;
    59. }
    60. public String getName() {
    61. return name;
    62. }
    63. public void setName(String name) {
    64. this.name = name;
    65. }
    66. public int getAge() {
    67. return age;
    68. }
    69. public void setAge(int age) {
    70. this.age = age;
    71. }
    72. }

    序列化和反序列化的注意事项和细节说明

    1)读写顺序要一致

    2)要求序列化或反序列化对象,需要 实现 Serializable

    3序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性

    4)序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员

    5)序列化对象时,要求里面属性的类型也需要实现序列化接口

    6)序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化

    标准输入输出流

    代码演示:

    1. package com.standard;
    2. import java.util.Scanner;
    3. public class InputAndOutput {
    4. public static void main(String[] args) {
    5. //System 类 的 public final static InputStream in = null;
    6. // System.in 编译类型 InputStream
    7. // System.in 运行类型 BufferedInputStream
    8. // 表示的是标准输入 键盘
    9. System.out.println(System.in.getClass());
    10. //解读
    11. //1. System.out public final static PrintStream out = null;
    12. //2. 编译类型 PrintStream
    13. //3. 运行类型 PrintStream
    14. //4. 表示标准输出 显示器
    15. System.out.println(System.out.getClass());
    16. System.out.println("hello, 你好~");
    17. Scanner scanner = new Scanner(System.in);
    18. System.out.println("输入内容");
    19. String next = scanner.next();
    20. System.out.println("next=" + next);
    21. }
    22. }

    转换流

    首先我们来看看为什么会出现乱码问题

    乱码问题

    那么乱码可能是以下原因导致的

    1. 编码不匹配:转换流可以将字节流转换成字符流,如果在转换的过程中使用了错误的编码方式,就会出现乱码问题。

    2. 字符集不支持:有些字符集在Java中不被支持,如果在转换流中使用了不支持的字符集,也会出现乱码问题。

    3. 字节流长度不匹配:如果转换流在读取字节流时,读取到的字节长度超出了字符流的长度限制,就会出现乱码问题。

    解决方法

    代码演示

    1. package com.transformation;
    2. import java.io.*;
    3. /**
    4. * 演示使用 InputStreamReader 转换流解决中文乱码问题
    5. * 将字节流 FileInputStream 转成字符流 InputStreamReader, 指定编码 gbk/utf-8
    6. */
    7. public class InputStreamReader_ {
    8. public static void main(String[] args) throws IOException {
    9. String filePath = "e:\\abc.txt";
    10. //解读
    11. //1. 把 FileInputStream 转成 InputStreamReader
    12. //2. 指定编码 gbk
    13. //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
    14. //3. 把 InputStreamReader 传入 BufferedReader
    15. //BufferedReader br = new BufferedReader(isr);
    16. //将2 和 3 合在一起
    17. BufferedReader br = new BufferedReader(new InputStreamReader(
    18. new FileInputStream(filePath), "gbk"));
    19. //4. 读取
    20. String s = br.readLine();
    21. System.out.println("读取内容=" + s);
    22. //5. 关闭外层流
    23. br.close();
    24. }
    25. }

  • 相关阅读:
    数据包络分析(DEA)——BCC模型
    ubuntu20.04 jammy 安装ros2
    Python绘制三维图详解
    基于SSM的校园预点餐网站
    beego语言golang编程语言安装bee : 无法将“bee”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
    记一次spark数据倾斜实践
    C#的反射机制
    Koltin协程:Flow的触发与消费
    深入理解KNN扩展到ANN
    机器视觉技术在现代汽车制造中的应用
  • 原文地址:https://blog.csdn.net/weixin_53616401/article/details/129480822