[Java-12] tabla de codificación, flujo de caracteres, flujo de objetos, otros flujos

contenido principal

  • tabla de códigos
  • flujo de salida de caracteres
  • flujo de entrada de caracteres
  • flujo de búfer de caracteres
  • flujo de conversión
  • flujo de operaciones de objetos
  • patrón decorador
  • paquete commons-iojar

1 tabla de códigos

1.1 Pensamiento:

  • Dado que los flujos de bytes pueden operar en todos los archivos, ¿por qué aprender flujos de caracteres?
    • Si utiliza un flujo de bytes, al leer el contenido del archivo de texto en la memoria, pueden aparecer caracteres ilegibles
    • Si usa un flujo de bytes para escribir chino en un archivo de texto, también puede haber caracteres ilegibles

1.2 Introducción a la tabla de códigos

  • La información almacenada en la computadora está representada por datos binarios; los caracteres ingleses, chinos y otros caracteres que vemos en la pantalla son el resultado de la conversión de números binarios

  • De acuerdo con las reglas de la tabla de códigos, los caracteres se almacenan en la computadora, lo que se denomina codificación.

  • De acuerdo con las mismas reglas de la tabla de codificación, los datos binarios almacenados en la computadora se analizan y muestran, lo que se denomina decodificación.

  • Las tablas de códigos utilizadas para codificar y decodificar deben ser coherentes; de lo contrario, se producirán caracteres distorsionados.

  • Comprensión sencilla:
    • Para almacenar un carácter a, primero debe encontrar el número 97 correspondiente en la tabla de códigos y luego almacenarlo de acuerdo con las reglas para convertirlo en binario. código
    • Al leer, primero analice el binario y luego conviértalo a 97, y use 97 para encontrar el carácter correspondiente en la tabla de código inicial es a. llamado decodificación
  • Tabla de códigos ASCII:
    • ASCII (Código estándar estadounidense para el intercambio de información, Código estándar estadounidense para el intercambio de información):
    • Incluyendo caracteres numéricos, caracteres en mayúsculas y minúsculas en inglés y algunos caracteres de puntuación comunes.
    • Nota: No hay chino en la tabla de códigos ASCII.

    [Falló la transferencia de la imagen del enlace externo, el sitio de origen puede tener un mecanismo anti-leeching, se recomienda guardar la imagen y cargarla directamente (img-nqQ7Nr8R-1685619059845)(img\image-20210415215825911.png)]

  • Tabla de códigos GBK:
    • La tabla de códigos predeterminada del sistema de ventanas. Compatible con la tabla de códigos ASCII, también contiene 21003 caracteres chinos y admite caracteres chinos tradicionales y algunos caracteres japoneses y coreanos
    • Nota: GBK es una tabla de códigos chinos y un chino se almacena en forma de dos bytes. Pero no contiene el texto de todos los países del mundo.
  • Tabla de códigos Unicode:
    • Desarrollada por la organización internacional ISO, es una tabla de códigos universales unificados, un estándar de la industria en el campo de la informática, que se adapta a todos los caracteres y símbolos comunes en la mayoría de los países del mundo.
    • Pero debido a que hay demasiados caracteres representados, los números en la tabla de códigos Unicode no se almacenan directamente en la computadora en forma binaria, sino que primero pasan a través de UTF-7, UTF-7.5, UTF-8, UTF-16 y UTF. -32 El método de codificación luego se almacena en la computadora, el más común de los cuales es UTF-8.
    • Nota: Unicode es una tabla de códigos universal y, después de la codificación UTF-8, el chino se almacena en forma de tres bytes.

1.4 El código original del flujo de bytes que lee el código de apariencia chino

  • Debido a que el flujo de bytes lee un byte a la vez, independientemente de GBK o UTF-8, un chino tiene varios bytes y el flujo de bytes solo puede leer una parte a la vez, por lo que habrá caracteres ilegibles.

Flujo de salida de 2 caracteres

2.1 Introducción a la salida de flujo de caracteres

  • clase de escritor
    • La clase de nivel superior que escribe secuencias de caracteres es una clase abstracta de la que no se puede crear una instancia, y se debe usar su clase de subclase FileWriter
  • Clase FileWriter: clase de conveniencia para escribir archivos de caracteres

2.2 Miembros de FileWriter

  • Método de construcción :

    • FileWriter público (archivo de archivo): escribe datos en la ruta de archivo especificada
    • public FileWriter (String fileName): escribe datos en la ruta de cadena especificada
  • Método de miembro:

    • escritura nula (int c) escribe un personaje
      escritura vacía (char[] cbuf) escribir una matriz de caracteres
      escritura vacía (char[] cbuf, int off, int len) escribir parte de la matriz de caracteres
      escritura vacía (String str) escribir una cadena
      void escribir(String str, int off, int len) escribir parte de una cadena
    • enjuagar() Actualizar la transmisión y continuar escribiendo datos
      cerca() Cierre la secuencia, liberando recursos, pero vaciando la secuencia antes de cerrarla. Una vez cerrado, ya no se pueden escribir datos

2.3 Pasos para que FileWriter escriba datos

  • 1 Crear un objeto de flujo de salida de caracteres
    • Nota:
      Si el archivo no existe, se creará. Pero asegúrese de que exista la ruta principal.
      Vaciar el archivo si existe
  • 2 escribir datos
    • Nota:
      Al escribir un entero de tipo int, lo que realmente se escribe es la letra correspondiente al entero en la tabla de códigos.
      Para escribir datos de cadena, la propia cadena se escribe tal cual.
  • 3 recursos de liberación
    • Nota:
      El recurso debe liberarse cada vez que se usa la transmisión.
  • package com.bn.writer_demo;
    
    import java.io.FileWriter;
    import java.io.IOException;
    
    /*
        Writer类 : 写入字符流的最顶层的类 , 是一个抽象类 ,不能实例化
        需要使用其子类FileWriter类
    
        FileWriter类 : 用来写入字符文件的便捷类
        构造方法 :
            public FileWriter(File file) : 往指定的File路径中写入数据
            public FileWriter(String fileName) : 往指定的String路径中写入数据
        成员方法
            void write​(int c)	写一个字符
            void write​(char[] cbuf)	写入一个字符数组
            void write​(char[] cbuf, int off, int len)	写入字符数组的一部分
            void write​(String str)	写一个字符串
            void write​(String str, int off, int len)	写一个字符串的一部分
            flush()	刷新流,还可以继续写数据
            close()	关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
     */
    public class WriterDemo1 {
          
          
        public static void main(String[] args) throws IOException {
          
          
            // 创建字符输出流对象
            // 如果文件不存在会创建一个空的文件
            // 如果文件存在 , 会把文件中的内容清空
            FileWriter fw = new FileWriter("day12_demo\\charstream2.txt");
    
            // 写数据
            fw.write('a');
            fw.write('b');
            // 刷新流 , 把流中的数据刷到硬盘中 , 刷新之后可以继续写数据
            // fw.flush();
    
            // 释放资源
            // 关闭流 , 但是会先刷新流
            fw.close();
            // 一旦关闭流无法写数据
            // fw.write('c');
        }
    }
    
    
    package com.bn.writer_demo;
    
    import java.io.FileWriter;
    import java.io.IOException;
    
    /*
        Writer类 : 写入字符流的最顶层的类 , 是一个抽象类 ,不能实例化
        需要使用其子类FileWriter类
    
        FileWriter类 : 用来写入字符文件的便捷类
        构造方法 :
            public FileWriter(File file) : 往指定的File路径中写入数据
            public FileWriter(String fileName) : 往指定的String路径中写入数据
        成员方法
            void write​(int c)	写一个字符
            void write​(char[] cbuf)	写入一个字符数组
            void write​(char[] cbuf, int off, int len)	写入字符数组的一部分
            void write​(String str)	写一个字符串
            void write​(String str, int off, int len)	写一个字符串的一部分
            flush()	刷新流,还可以继续写数据
            close()	关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
     */
    public class WriterDemo2 {
          
          
        public static void main(String[] args) throws IOException {
          
          
            // 创建字符输出流对象
            FileWriter fw = new FileWriter("day12_demo\\charstream2.txt");
    
            // 写数据
    //        void write​(int c)	写一个字符
    //        fw.write('a');
    //        fw.write('b');
    //        fw.write('c');
    
    //        void write​(char[] cbuf)	写入一个字符数组
            char[] chs = {
          
          'a', 'b', 'c', 'd', 'e'};
    //        fw.write(chs);
    
    //        void write​(char[] cbuf, int off, int len)	写入字符数组的一部分
    //        fw.write(chs , 2 , 3);
    
    //        void write​(String str)	写一个字符串
    //        fw.write("abcadaasda");
    
    //        void write​(String str, int off, int len)	写一个字符串的一部分
    //        fw.write("abnacna", 3, 2);
    
            // 释放资源
            fw.close();
        }
    }
    
    

2.4 Ejercicios de flujo de salida de caracteres

  • package com.bn.writer_demo;
    
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.Scanner;
    
    /*
        需求 : 将用户键盘录入的用户名和密码保存到本地实现永久化存储。
        要求 : 用户名和密码在文件中各占一行
    
        步骤:
            1 用户键盘录入用户名
            2 创建字符输出流对象
            3 将用户名和密码写到本地文件中
     */
    public class WriterTest {
          
          
        public static void main(String[] args) throws IOException {
          
          
            Scanner sc = new Scanner(System.in);
            System.out.println("请输入用户名:");
            String username = sc.nextLine();
    
            System.out.println("请输入密码:");
            String password = sc.nextLine();
    
            // 创建字符输出流对象
            FileWriter fw = new FileWriter("day12_demo\\user.txt");
            // 往文件中写入用户名和密码
            fw.write(username);
            // 换行
            fw.write("\r\n");
            fw.write(password);
            // 刷新
            fw.flush();
            // 释放资源
            fw.close();
        }
    }
    
    

flujo de entrada de 3 caracteres

3.1 Introducción al flujo de entrada de bytes

  • Clase de lector:
    • La clase de nivel superior que lee flujos de caracteres es una clase abstracta que no se puede instanciar
    • Necesita usar su clase de subclase FileReader
  • Clase de lector de archivos:
    • Clase de conveniencia para leer archivos de caracteres

3.2 Miembros de FileReader

  • Método de construcción :

    • FileReader público (archivo de archivo): leer datos de la ruta de archivo especificada
    • public FileReader (String fileName): lee datos de la ruta de cadena especificada
  • Método de miembro:

    • lectura int() Lee los datos de los personajes uno a la vez
      lectura int(char[] cbuf) Leer datos de matriz de caracteres uno a la vez
  • package com.bn.reader_demo;
    
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    
    /*
        Reader类 : 读取字符流的最顶层的类 , 是一个抽象类 ,不能实例化
        需要使用其子类FileReader类
    
        FileReader类 : 用来读取字符文件的便捷类
    
        构造方法 :
            public FileReader(File file) : 从指定的File路径中读取数据
            public FileReader(String fileName) : 从指定的String路径中读取数据
    
        成员方法 :
            int read​() : 一次读一个字符数据
            int read​(char[] cbuf)	 : 一次读一个字符数组数据
     */
    public class ReaderDemo1 {
          
          
        public static void main(String[] args) throws IOException {
          
          
            // 创建字符输入流对象
            FileReader fr = new FileReader("day12_demo\\charstream.txt");
    
            // 一次读一个字符数据
            int ch;
            while ((ch = fr.read()) != -1) {
          
          
                System.out.print((char) ch);
            }
    
            // 释放资源
            fr.close();
        }
    }
    
    
  • package com.bn.reader_demo;
    
    import java.io.FileNotFoundException;
    import java.io.FileReader;
    import java.io.IOException;
    
    /*
        Reader类 : 读取字符流的最顶层的类 , 是一个抽象类 ,不能实例化
        需要使用其子类FileReader类
    
        FileReader类 : 用来读取字符文件的便捷类
    
        构造方法 :
            public FileReader(File file) : 从指定的File路径中读取数据
            public FileReader(String fileName) : 从指定的String路径中读取数据
    
        成员方法 :
            int read​()	一次读一个字符数据
            int read​(char[] cbuf)	一次读一个字符数组数据
     */
    public class ReaderDemo2 {
          
          
        public static void main(String[] args) throws IOException {
          
          
            // 创建字符输入流对象
            FileReader fr = new FileReader("day12_demo\\charstream.txt");
    
            // 一次读一个字符数组数据
            char[] chs = new char[1024];
            int len;
            while ((len = fr.read(chs)) != -1) {
          
          
                System.out.println(new String(chs, 0, len));
            }
            // 释放资源
            fr.close();
        }
    }
    
    

Flujo almacenado en búfer de 4 caracteres

4.1 Flujo de búfer de caracteres

  • BufferedWriter: puede escribir datos de manera eficiente
  • BufferedReader: puede leer datos en la memoria de manera eficiente
  • Nota: El flujo de búfer de caracteres no tiene la función de lectura y escritura, solo proporciona un búfer, y la lectura y escritura reales aún deben depender del flujo de caracteres básico recibido por la construcción.
  • Método de construcción:
    • public BufferedWriter (Writer out): el método de construcción debe recibir un flujo de salida de caracteres básico
    • public BufferedReader (Reader in): el método de construcción debe recibir un flujo de entrada de caracteres básico
package com.bn.bufferedstream_demo;

import java.io.*;

/*
    需求 : 使用字符缓冲流复制纯文本文件
    将当日课程资料中的 ‘斗罗大陆.txt’ 复制到当前模块下 'copy.txt'
 */
public class BufferedStreamDemo1 {
    public static void main(String[] args) throws IOException {
        // 创建高效的字符输入流对象
        BufferedReader br = new BufferedReader(new FileReader("D:\\传智播客\\上海-JavaSE进阶面授\\day12【缓冲流、转换流、序列化流、装饰者模式、commons-io工具包】\\资料\\斗罗大陆.txt"));
        // 创建高效的字符输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("day12_demo\\copy.txt"));

        // 一次读写一个字符
//        int ch;
//        while ((ch = br.read()) != -1) {
//            bw.write(ch);
//        }

        // 一次读写一个字符数组
        char[] chs = new char[1024];
        int len;
        while ((len = br.read(chs)) != -1) {
            bw.write(chs, 0, len);
        }
        // 释放资源
        br.close();
        bw.close();
    }
}

4.2 Características específicas de los flujos de búfer de caracteres

  • clase BufferedWriter
    • void newLine(): escriba un separador de línea, que escribirá diferentes separadores de línea según el sistema operativo
  • Clase BufferedReader
    • public String readLine() : lee una línea de datos del archivo, no contiene el símbolo de nueva línea y devuelve nulo al leer hasta el final del archivo
  • package com.bn.bufferedstream_demo;
    
    import java.io.*;
    
    /*
        1 字符缓冲流:
            BufferedWriter:可以将数据高效的写出
            BufferedReader:可以将数据高效的读入到内存
    
        2 字符缓冲流特有功能
            BufferedWriter类
                void newLine​():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符
            BufferedReader类
                public String readLine​() :读取文件一行数据, 不包含换行符号 ,  读到文件的末尾返回null
    
            远桥之下泛莲舟
            岱岩石上松溪流
            万仞翠山梨亭在
            莫闻空谷声悠悠
     */
    public class BufferedStreamDemo2 {
          
          
        public static void main(String[] args) throws IOException {
          
          
    
            // 创建高效的字符输出流对象
            BufferedWriter bw = new BufferedWriter(new FileWriter("day12_demo\\abc.txt"));
            // void newLine​():写一个行分隔符,会根据操作系统的不同,写入不同的行分隔符
            bw.write("远桥之下泛莲舟");
            bw.newLine();
            bw.write("岱岩石上松溪流");
            bw.newLine();
            bw.write("万仞翠山梨亭在");
            bw.newLine();
            bw.write("莫闻空谷声悠悠");
            bw.flush();
    
            // 创建高效的字符输入流对象
            BufferedReader br = new BufferedReader(new FileReader("day12_demo\\abc.txt"));
            // public String readLine​() :读取文件一行数据, 不包含换行符号 ,  读到文件的末尾返回null
    //        String s = br.readLine();
    //        System.out.println(s);
    //        s = br.readLine();
    //        System.out.println(s);
    //        s = br.readLine();
    //        System.out.println(s);
    //        s = br.readLine();
    //        System.out.println(s);
    //        System.out.println("============");
    //        s = br.readLine();
    //        System.out.println(s);
    //        s = br.readLine();
    //        System.out.println(s);
    
            // 循环改进
            String line;
            while((line = br.readLine()) != null){
          
          
                System.out.println(line);
            }
    
            // 释放资源
            br.close();
            bw.close();
        }
    }
    
    

4.3 Ejercicio de flujo de búfer de caracteres

package com.bn.bufferedstream_demo;

import java.io.*;
import java.util.Arrays;

/*
    需求:读取文件中的数据 : 33 22 11 55 44
    排序后 : 11 22 33 44 55  再次写到本地文件

    步骤 :
        1 创建高效的字符输入流对象
        2 读取文件中的一行数据
        3 将数据按照空格切割
        4 把字符串数组转成int类型数组
        5 对int类型的数组进行排序
        6 创建高效的字符输出流对象
        7 遍历数组,把数组中的数据写入到文件中
        8 释放资源
 */
public class BufferedStreamDemo3 {
    public static void main(String[] args) throws IOException {
        // 1 创建高效的字符输入流对象
        BufferedReader br = new BufferedReader(new FileReader("day12_demo\\sort.txt"));
        // 2 读取文件中的一行数据
        String line = br.readLine();
        // 3 将数据按照空格切割
        String[] strs = line.split(" ");
        // 4 把字符串数组转成int类型数组
        int[] arr = new int[strs.length];
        for (int i = 0; i < strs.length; i++) {
            arr[i] = Integer.parseInt(strs[i]);
        }
        // 5 对int类型的数组进行排序
        Arrays.sort(arr);
        // 6 创建高效的字符输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("day12_demo\\sort.txt"));
        // 7 遍历数组,把数组写入到文件中
        for (int i = 0; i < arr.length; i++) {
            bw.write(arr[i] + " ");
            bw.flush();
        }
        // 8 释放资源
        br.close();
        bw.close();
    }
}

5 flujo de conversión

5.1 Introducción al flujo de transformación

  • El flujo de conversión es un puente para convertir entre flujos de bytes y flujos de caracteres.

5.2 Clasificación del flujo de transformación

  • InputStreamReader es un puente entre el flujo de bytes y el flujo de caracteres

    • público InputStreamReader(InputStream in) : crea un InputStreamReader utilizando la codificación predeterminada.
    • public InputStreamReader(InputStream in , String charsetName) : crea un InputStreamReader utilizando la codificación especificada.
  • OutputStreamWriter es un puente entre el flujo de caracteres y el flujo de bytes

    • Public OutputStreamWriter (OutputStream out): cree un OutputStreamWriter que use la codificación de caracteres predeterminada
    • public OutputStreamWriter(OutputStream out, String charsetName) : crea un OutputStreamWriter utilizando la codificación especificada.
  • práctica
    package com.bn.conversion_demo;
    
    import java.io.*;
    
    /*
        转换流就是来进行字节流和字符流之间转换的桥梁
    
        InputStreamReader是从字节流到字符流的桥梁
            public InputStreamReader(InputStream in) : 创建一个使用默认编码的 InputStreamReader。
            public InputStreamReader(InputStream in ,  String charsetName) : 创建使用指定编码的 InputStreamReader。
    
        OutputStreamWriter是从字符流到字节流的桥梁
            public OutputStreamWriter(OutputStream out) : 创建使用默认字符编码的 OutputStreamWriter
            public OutputStreamWriter(OutputStream out,  String charsetName) : 创建使用指定编码的 OutputStreamWriter。
    
    
        需求1 : 使用转换流 , 把以下数据按照GBK的编码写入文件 , 在使用GBK的编码读取数据
        数据如下 :
            远桥之下泛莲舟
            岱岩石上松溪流
            万仞翠山梨亭在
            莫闻空谷声悠悠
     */
    public class ConversionDemo2 {
          
          
        public static void main(String[] args) throws IOException {
          
          
            // 创建转换输出流
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12_demo\\conversion.txt"), "GBK");
            osw.write("远桥之下泛莲舟");
            osw.write("\r\n");
            osw.write("岱岩石上松溪流");
            osw.write("\r\n");
            osw.write("万仞翠山梨亭在");
            osw.write("\r\n");
            osw.write("莫闻空谷声悠悠");
            osw.write("\r\n");
            osw.close();
    
            // 创建转换输入流
            InputStreamReader isr = new InputStreamReader(new FileInputStream("day12_demo\\conversion.txt"), "GBK");
            int ch;
            while ((ch = isr.read()) != -1) {
          
          
                System.out.print((char) ch);
            }
            isr.close();
        }
    }
    
    
    package com.bn.conversion_demo;
    
    import java.io.*;
    
    /*
        转换流就是来进行字节流和字符流之间转换的桥梁
    
        InputStreamReader是从字节流到字符流的桥梁
            public InputStreamReader(InputStream in) : 创建一个使用默认编码的 InputStreamReader。
            public InputStreamReader(InputStream in ,  String charsetName) : 创建使用指定编码的 InputStreamReader。
    
        OutputStreamWriter是从字符流到字节流的桥梁
            public OutputStreamWriter(OutputStream out) : 创建使用默认字符编码的 OutputStreamWriter
            public OutputStreamWriter(OutputStream out,  String charsetName) : 创建使用指定编码的 OutputStreamWriter。
    
        需求2 :  将模块根目录中GBK编码的文本文件 , 转换为UTF-8编码的文本文件
     */
    public class ConversionDemo2 {
          
          
        public static void main(String[] args) throws IOException {
          
          
    
            // 创建转换输入流
            InputStreamReader isr = new InputStreamReader(new FileInputStream("day12_demo\\GBK编码的文件.txt"), "GBK");
    
            // 创建转换输出流
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("day12_demo\\UTF编码的文件.txt"), "UTF-8");
    
            int ch;
            while ((ch = isr.read()) != -1) {
          
          // 以GBK编码进去读取
                osw.write(ch);// 以UTF-8编码进行写入
            }
    
            // 释放资源
            isr.close();
            osw.close();
        }
    }
    
    

6 Flujo de operaciones de objetos

6.1 Introducción al flujo de operación de objetos

  • Puede escribir el objeto en el archivo local en forma de bytes, abrir el archivo directamente, es ilegible, necesita usar el flujo de operación del objeto para leerlo en la memoria nuevamente

6.2 Clasificación del flujo de operaciones de objetos

  • ObjetoOutputStream:
    • Flujo de salida de operación de objeto (flujo de serialización de objeto): es para escribir el objeto en un archivo local o transferir el objeto en la red
  • ObjetoEntradaStream:
    • Flujo de entrada de operación de objeto (flujo de deserialización de objeto): lea el objeto escrito en el archivo local en la memoria, o reciba el objeto transmitido en la red

6.3 Consideraciones para el flujo de operación de objetos

  • Nota: si un objeto de clase desea serializarse, esta clase debe implementar la interfaz Serializable

    • El significado de la interfaz Serializable:
      • 1 es una interfaz marcada sin ningún método abstracto
      • 2 Siempre que una clase implemente esta interfaz, significa que los objetos de esta clase se pueden serializar
  • Después de serializar un objeto con el flujo de serialización de objetos, si modificamos la clase Javabean a la que pertenece el objeto, ¿habrá problemas para leer los datos?

    • Habrá problemas y se lanzará una InvalidClassException
  • Si algo sale mal, ¿cómo solucionarlo?

    • Agregue un serialVersionUID a la clase a la que pertenece el objeto
    • privado estático final largo serialVersionUID = 42L;
  • Si el valor de una variable miembro en un objeto no quiere ser serializado, ¿cómo lograrlo?

  • Agregue la palabra clave transitoria a la variable miembro, y la variable miembro marcada por esta palabra clave no participa en el proceso de serialización

  • package com.bn.objectstream_demo;
    
    
    import java.io.Serializable;
    
    /*
        如果此类对象想要被序列化 , 那么此类需要实现Serializable接口
        Serializable接口的含义 :
            是一个标记性接口 , 里面没有任何抽象方法
            只要一个类实现了此接口 , 表示此类的对象可以被序列化
     */
    public class User implements Serializable {
        /*
            问题分析 :
                serialVersionUID : 序列号
                序列号是根据类的信息进行生成的
                如果没有自己给出序列号 , JVM会根据类的信息自动计算一个序列号
                如果改动了类的信息 , 那么JVM会重新计算一个序列号
    
                第一步 : 把对象序列化到本地中 , 序列号为 -4446663370728791812 也会存储到本地中
                第二步 : 我们自己修改了类 , 会重新计算一个新的序列号 2908680347500030933
                第三步 : 当把对象读到内存中时 , 本地中的序列号和类中的序列号不一致就会发生 InvalidClassException异常
    
            解决方案 :
                我们自己手动给出序列号, 不让虚拟机自动生成 , 并且这个值恒久不变
                private static final long serialVersionUID = 值L;
         */
    
        private static final long serialVersionUID = 111L;
    
        private String username;
        private transient String password;
    
        public User() {
        }
    
        public User(String username, String password) {
            this.username = username;
            this.password = password;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
    }
    

6.4 Ejercicios sobre flujo de manipulación de objetos

7 patrones de diseño decorativo

  • Patrón de diseño: un conjunto de buen estilo de codificación, que se resume después de pruebas continuas por parte de muchos desarrolladores.

objetivo de aprendizaje

  • Familiaridad con el uso del patrón de diseño Decorator.

Explicación del contenido

【1. Información general

  • El modo de decoración se refiere a extender dinámicamente la función de un objeto sin cambiar la clase original y sin usar la herencia.

  • No use la tecnología de herencia para expandir funciones, lo que puede reducir el acoplamiento

  • Principios de uso:
    • La clase de decoración y la clase decorada deben tener un tipo principal común.
      • El BufferedWriter y FileWriter aprendidos antes son los patrones de diseño de decoración
      • La clase principal de BufferedWriter es Writer
      • La clase principal de FileWriter también es Writer
      • Pasamos el objeto FileWriter a la construcción de BufferedWriter, para que se entienda que BufferedWriter es una clase decorada, y FileWriter es una clase decorada.
      • BufferedWriter ha mejorado la función de FileWriter
    • El constructor de la clase decorada necesita recibir el objeto de la clase decorada.
      • FileWriter fw = new FileWriter("ruta");
      • BufferedWriter bw = new BufferedWriter(fw);
    • Ampliar la función para ser mejorada y ampliada en la clase de decoración.
      • BufferedWriter tiene la misma función que FileWriter, ambos tienen la función de escribir datos en Writer
      • Pero BufferedWriter proporciona un búfer, que es equivalente a extender la función de FileWriter
    • Llame directamente para funciones que no se pueden mejorar
      • No se pueden heredar funciones mejoradas directamente de la clase principal

[2] Código de práctica

Se sabe que existe una interfaz Star y su subtipo LiuDeHua.

public interface Star {
    
    
    public abstract void sing();
    public abstract void dance();
}

Requisitos: extienda dinámicamente la función de cantar de LiuDeHua sin cambiar la clase de LiuDeHua y sin usar técnicas de herencia.

LiuDeHua es una clase decorada que necesita expandir la función de canto.

Ideas:

Defina una clase de decoración para decorar y mejorar la clase LiuDehua.

paso:

  • Cree la clase LiuDeHua e implemente la interfaz Star [clase decorada]

  • Defina una clase de decoración LiuDeHuaWrapper para implementar Star [clase de decoración]

  • Defina un tipo de variable miembro en la clase de decoración como LiuDeHua, y puede usar el constructor para pasar el objeto de clase decorado.

  • Ampliar la función del método sing en la clase de decoración.

  • no hay cambio para bailar

  • La clase de prueba crea objetos de la clase de decoración y objetos de la clase decorada respectivamente. Establezca el objeto de clase decorado Andy Lau objeto en el objeto de clase decorado

package com.bn.design_demo;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Scanner;

/*
    装饰模式指的是在不改变原类, 不使用继承的基础上,动态地扩展一个对象的功能

    使用原则 :
        1. 装饰类和被装饰类需要有共同的父类型。
        2. 装饰类要传入被装饰类的对象
        3. 在装饰类中把要增强扩展的功能进行扩展
        4. 对于不要增强的功能直接调用


    需求 : 在不改变LiuDeHua类,及不使用继承的技术前提下,动态的扩展LiuDeHua的sing功能。
            LiuDeHua就是一个被装饰类 , 需要对唱歌的功能进行扩展
    步骤:
        1. 创建LiuDeHua类并实现接口Star【被装饰类】
        2. 定义一个装饰类LiuDeHuaWrapper实现Star 【装饰类】
        3. 在装饰类里面定义一个成员变量类型是LiuDeHua,可以使用构造方法进行传入被装饰类对象。
        4. 在装饰类中对sing方法进行功能扩展
        5. 对dance不做改动
        6. 测试类分别创建装饰类的对象和被装饰类的对象。将被装饰类对象刘德华对象设置给装饰类对象
 */
public class Test {
    
    
    public static void main(String[] args) throws IOException {
    
    
        // 被装饰类对象
        LiuDeHua huaZai = new LiuDeHua();// 0x001

        // 装饰类对象
        LiuDeHuaWrapper liuDeHuaWrapper = new LiuDeHuaWrapper(huaZai);
        liuDeHuaWrapper.sing();
        liuDeHuaWrapper.dance();

//        // 被装饰类对象
//        FileWriter fw = new FileWriter("路径");
//        // 装饰类对象
//        BufferedWriter bw = new BufferedWriter(fw);
    }
}


// 1. 创建LiuDeHua类并实现接口Star【被装饰类】
class LiuDeHua implements Star {
    
    

    @Override
    public void sing() {
    
    
        System.out.println("唱忘情水...");
    }

    @Override
    public void dance() {
    
    
        System.out.println("华仔在跳老年迪斯高..");
    }
}

// 2. 定义一个装饰类LiuDeHuaWrapper实现Star 【装饰类】
class LiuDeHuaWrapper implements Star {
    
    
    // 3. 在装饰类里面定义一个成员变量类型是LiuDeHua,可以使用构造方法进行传入被装饰类对象。
    private LiuDeHua huaZai;// 0x001

    public LiuDeHuaWrapper(LiuDeHua huaZai) {
    
    // 0x001
        this.huaZai = huaZai;
    }

    @Override
    public void sing() {
    
    
        // 4. 在装饰类中对sing方法进行功能扩展
        System.out.print("华仔深情");
        huaZai.sing();
    }

    @Override
    public void dance() {
    
    
        // 5. 对dance不做改动
        huaZai.dance();
    }
}


// 明星接口 , 装饰类和被装饰类的父类型
interface Star {
    
    
    public abstract void sing(); // 唱歌

    public abstract void dance();// 跳舞
}

Resumen de contenido

  1. La clase de decoración y la clase decorada deben tener un tipo principal común.
  2. La clase de decoración debe pasar en el objeto de la clase decorada.
  3. Ampliar la función para ser mejorada y ampliada en la clase de decoración.
  4. Llame directamente para funciones que no se pueden mejorar

9 kit de herramientas commons-io (optimizar la copia de archivos)

Objetivo

  • Familiarícese con la importación del kit de herramientas commons-io y el uso

Explicación del contenido

[1] Importación de biblioteca tripartita

  1. Descargue paquetes jar relacionados con commons-io; http://commons.apache.org/proper/commons-io/

  2. Copie el paquete commons-io-2.6.jar en el directorio lib del módulo especificado

  3. Agregue commons-io-2.6.jar al proyecto

【2】API

1) clase org.apache.commons.io.IOUtils

public static int copy(InputStream in, OutputStream out):
	把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以下)
    
public static long copyLarge(InputStream in, OutputStream out):
	把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以上)

package com.bn.commons_io;

import org.apache.commons.io.IOUtils;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*
    org.apache.commons.io.IOUtils类

    public static int copy(InputStream in, OutputStream out):
	把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以下)

    public static long copyLarge(InputStream in, OutputStream out):
	把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以上)
 */
public class Test1 {
    
    
    public static void main(String[] args) throws IOException {
    
    
        IOUtils.copy(new FileInputStream("D:\\安装包\\好看的图片\\liqin.jpg") , new FileOutputStream("day12_demo\\copy.jpg"));
    }
}

2)org.apache.commons.io.FileUtils

public static void copyFileToDirectory(final File srcFile, final File destFile): 
	复制文件到另外一个目录下。
public static void copyDirectoryToDirectory(File src , File dest ):
	复制src目录到dest位置。

Código de práctica:

package com.bn.commons_io;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;

/*
    org.apache.commons.io.FileUtils

    public static void copyFileToDirectory(final File srcFile, final File destFile):
	复制文件到另外一个目录下。

    public static void copyDirectoryToDirectory(File src , File dest ):
	复制src目录到dest目录中。
 */
public class Test2 {
    
    
    public static void main(String[] args) throws IOException {
    
    
        FileUtils.copyDirectoryToDirectory(new File("D:XX") , new File("D:"));
    }
}

Resumen de contenido

commons-io puede simplificar la operación de copia de archivos IO.

Supongo que te gusta

Origin blog.csdn.net/wanghaoyingand/article/details/130994665
Recomendado
Clasificación