Resumen de los puntos de conocimiento del flujo de E/S de JAVA

Cómo se creó el archivo

Primero observe el constructor de la clase File y concluya que hay tres formas comunes de crear
inserte la descripción de la imagen aquí

Pase directamente la ruta del archivo construido, a través del constructor File(String pathname), pase directamente la ruta del archivo, el siguiente es el código de demostración (la operación del flujo IO siempre va acompañada de una excepción en tiempo de compilación, puede usar la excepción de tecla de método abreviado Alt+Intro detectada o lanzada)

public void create01()  {
    
    
    String filePath = "d:\\IOTest\\test1.txt";
    File file = new File(filePath);
    try {
    
    
        file.createNewFile();
        System.out.println("文件创建成功");
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

Especifique el archivo de directorio principal, es decir, el archivo de carpeta especificado + el archivo de subruta, y cree el archivo a través del constructor Archivo (Archivo principal, Cadena secundaria)

public void create02() {
    
    
    File parentFile = new File("d:\\IOTest");
    String fileName = "test2.txt";
    File file = new File(parentFile, fileName);

    try {
    
    
        file.createNewFile();
        System.out.println("创建成功");
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

Especifique directamente el directorio principal y el nombre del archivo, a través del constructor Archivo (String parent, String child)

public void create03() {
    
    
    String parentPath = "d:\\IOTest";
    String fileName = "test3.txt";
    File file = new File(parentPath, fileName);
    try {
    
    
        file.createNewFile();
        System.out.println("创建成功");
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

Operaciones comunes de archivos

ver información del archivo

El documento api de la clase de archivo File, desde el cual podemos ver que la clase File proporciona muchas API para que podamos ver la información del archivo, no es necesario memorizarlo de memoria, debe consultar el documento api

inserte la descripción de la imagen aquí

El siguiente es un ejemplo de API para obtener información común sobre archivos

public void info(){
    
    
    File file = new File("d:\\IOTest\\test1.txt");
    System.out.println("文件名字="+file.getName());
    System.out.println("文件的绝对路径="+file.getAbsolutePath());
    System.out.println("文件父级目录="+file.getParent());
    System.out.println("文件大小(字节)="+file.length());
    System.out.println("文件是否存在="+file.exists());
    System.out.println("是不是一个文件="+file.isFile());
    System.out.println("是不是一个目录="+file.isDirectory());
}

inserte la descripción de la imagen aquí

eliminación de archivos

Simplemente especifique la ruta del archivo, cree un objeto de archivo y llame al método de eliminación para completar la eliminación. Al eliminar un directorio, debe asegurarse de que esté vacío; de lo contrario, la eliminación fallará, pero no se producirá ninguna excepción.

String filePath = "d:\\IOTest\\test2.txt";
File file = new File(filePath);
if(file.exists()){
    
    
    if(file.delete()){
    
    
        System.out.println(filePath+"删除成功");
    }else{
    
    
        System.out.println(filePath+"删除失败");
    }
}else{
    
    
    System.out.println("该文件不存在...");
}

crear un directorio

Para crear un directorio de primer nivel, puede llamar directamente a mkdir() para crearlo con éxito, pero si está creando un directorio de varios niveles, debe usar mkdirs; de lo contrario, no se podrá crear el directorio, pero no se producirá ninguna excepción. ser arrojado

public void m3(){
    
    
    String directoryPath = "D:\\demo\\a\\b\\c";
    File file = new File(directoryPath);
    if(file.exists()){
    
    
        System.out.println(directoryPath+"存在...");
    }else{
    
    
        if(file.mkdirs()){
    
    
            System.out.println(directoryPath+"创建成功...");
        }else{
    
    
            System.out.println(directoryPath+"创建失败");
        }
    }
}

Principio de flujo IO y clasificación de flujo

concepto de OI

I/O es la abreviatura de Input/Output. La tecnología I/O es una tecnología muy práctica para procesar la transmisión de datos, la comunicación en red y la lectura y escritura de archivos. El paquete java.io proporciona clases e interfaces para varias interfaces de flujo. Se utiliza para procesar diferentes datos y datos de entrada o salida a través de api

Entrada Entrada: se refiere a la entrada de datos del disco a la memoria

Salida Salida: se refiere a la salida de datos de la memoria al disco

Clasificación de flujos IO

Clasificados por tipo de datos de operación: divididos en flujo de bytes (procesamiento de archivos binarios como audio, imágenes, video, etc.) y flujo de caracteres (procesamiento de texto)

Según la dirección del flujo del flujo de datos: dividido en flujo de entrada y flujo de salida

Clasificado según el rol del flujo: flujo de nodo, flujo de procesamiento/flujo de empaquetado (modo decorador)

clase base abstracta flujo de bytes flujo de caracteres
flujo de entrada Flujo de entrada Lector
flujo de salida Flujo de salida Escritor

archivos y flujos

Los archivos y los flujos son equivalentes a la relación entre productos y paquetes. Los productos deben empaquetarse en paquetes antes de que puedan transportarse, y la información de los archivos también debe convertirse en flujos antes de que puedan transmitirse entre el disco y la memoria. Paquetes ya contienen productos básicos. Si copia Para productos básicos, solo necesita copiar un paquete idéntico. Es por eso que al copiar un archivo, solo necesita copiar el flujo de entrada correspondiente del archivo al flujo de salida. La razón es que el flujo de entrada ya tiene toda la información del archivo antes de poder copiar el archivo.

Clases de flujo de E/S comúnmente utilizadas

flujo de entrada de bytes InputStream

InputStream como clase principal abstracta tiene principalmente las siguientes subclases

inserte la descripción de la imagen aquí

Flujo de entrada de FileInputStream

El archivo hello.txt con hello world se prepara de antemano en el disco D. En este momento, los enteros leídos son los valores ASCII de cada carácter. El método de lectura devolverá -1 después de leer el final del archivo, lo que indica que no hay más bytes para leer.

 		String filePath = "d:\\hello.txt";
        int readDate = 0;
        //提升作用域,用于在finally关闭输入流
        FileInputStream fileInputStream = null;
        try {
    
    
            fileInputStream = new FileInputStream(filePath);
            //一次读入一个字节,读到最后返回-1,表示无数据
            while ((readDate = fileInputStream.read()) != -1) {
    
    
                //每次将读入的字节数据转化为字符并输出
                System.out.print((char) readDate);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                //关闭流
                fileInputStream.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

inserte la descripción de la imagen aquí

El método anterior genera un problema, es decir, cada vez que se accede al disco desde la memoria, solo se puede leer un byte, y se necesitan 11 bytes para acceder al disco 11 veces. Los estudiantes que han estudiado el sistema operativo saben que acceder al disco de la memoria es muy difícil Una acción requiere mucho tiempo, por lo que para resolver este problema, el diseñador de Java proporciona un método de sobrecarga del búfer en el método read() de FileInputStream, que puede especificar el tamaño de el búfer para determinar el tamaño del búfer que se puede leer en un acceso al disco El número de bytes, lo que reduce el número de accesos al disco y optimiza el rendimiento.

  String filePath = "d:\\hello.txt";
        int readDate = 0;
//        指定一个8字节的字节数组作为缓冲区
        byte[] buf = new byte[8];
        FileInputStream fileInputStream = null;
        int readLen = 0;
        try {
    
    
            fileInputStream = new FileInputStream(filePath);
            while ((readLen = fileInputStream.read(buf)) != -1) {
    
    
//                每次将读取到的字节数据转为字符串输出
                System.out.print(new String (buf,0,readLen));
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                fileInputStream.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

Podemos ver que 8 caracteres de ASCII se leen directamente en la matriz de bytes del búfer

inserte la descripción de la imagen aquí

Pero sin un búfer, solo se puede leer uno a la vez, y la brecha de rendimiento es grande
inserte la descripción de la imagen aquí

Flujo de salida de bytes OutputStream

FileOutputStream

inserte la descripción de la imagen aquí

De forma predeterminada, el método de escritura de FileOutputStream es sobrescribir el contenido del archivo original. Si desea utilizar el método de escritura de anexar, debe asignar append a verdadero al crear el objeto para habilitar el modo de escritura de anexar. Al mismo tiempo, cuando el archivo no existe, el archivo se creará automáticamente, pero asegúrese de que el directorio existe

inserte la descripción de la imagen aquí

String filePath = "d:\\IOTest\\outTest.txt";
FileOutputStream fileOutputStream = null;
try {
    
    
    fileOutputStream = new FileOutputStream(filePath,true);
    String str = "hello,world";
    fileOutputStream.write(str.getBytes());
} catch (IOException e) {
    
    
    e.printStackTrace();
} finally {
    
    
    try {
    
    
        fileOutputStream.close();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }

Use FileOutputStream y FileInputStream para realizar la copia de archivos

Los pasos generales se dividen en dos pasos.

  1. Cree un flujo de entrada para un archivo y lea el archivo en el programa
  2. Cree el flujo de salida del archivo y escriba los datos del archivo leído en el archivo especificado
 		//文件路径
        String srcFilePath = "D:\\IOTest\\3e405d5c5b640f81caac8b4e551f7f33841232cd_raw.jpg";
        //拷贝的文件路径
        String destFilePath = "D:\\IOTest\\kakaxi.jpg";
        //输出流
        FileOutputStream fileOutputStream = null;
        //输入流
        FileInputStream fileInputStream = null;
        try {
    
    
            fileInputStream = new FileInputStream(srcFilePath);
            fileOutputStream = new FileOutputStream(destFilePath);
            //开辟1024个字节的缓冲区
            byte[] buf = new byte[1024];
            int readLen = 0;
            while ((readLen = fileInputStream.read(buf)) != -1){
    
    
                //将读到的文件信息写入新文件
                fileOutputStream.write(buf,0,readLen);
            }
        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
                //判断非空,防止出现空指针异常
            if(fileInputStream!=null){
    
    
                    fileInputStream.close();
                }
            if(fileOutputStream!=null){
    
    
                fileOutputStream.close();
            }}catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

copia normal de archivos

inserte la descripción de la imagen aquí

Flujo de entrada de caracteres FileReader

API relacionadas

inserte la descripción de la imagen aquí

ejemplo de código

String filePath = "d:\\IOTest\\story.txt";
FileReader fileReader = null;
int date = 0;
try {
    
    
    fileReader= new FileReader(filePath);
    while((date = fileReader.read())!=-1){
    
    
        System.out.print((char)date);
    }
} catch (IOException e) {
    
    
    e.printStackTrace();
}finally {
    
    
    try {
    
    
        fileReader.close();
    } catch (IOException e) {
    
    
        e.printStackTrace();
    }
}

El flujo de caracteres se usa especialmente para procesar archivos de texto. Podemos ver los caracteres leídos por FileReader. No hay caracteres ilegibles en los caracteres chinos. Tenga en cuenta que el método de lectura devuelve el valor ASCII de los caracteres. FileReader también puede especificar el búfer, y la descripción no se repetirá aquí.

inserte la descripción de la imagen aquí

Flujo de salida de caracteres FileWriter

API relacionadas

inserte la descripción de la imagen aquí

ejemplo de código

 String filePath = "d:\\IOTest\\note.txt";
        FileWriter fileWriter = null;
        char[] chars = {
    
    'a', 'b', 'c'};
        try {
    
    
            fileWriter = new FileWriter(filePath);
            fileWriter.write('H');
            fileWriter.write("学java狠狠赚一笔");
            fileWriter.write(chars);

        } catch (IOException e) {
    
    
            e.printStackTrace();
        } finally {
    
    
            try {
    
    
//                对于FileWriter,一定要关闭流,或者flush才能真正将数据写入到文件中
                fileWriter.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

inserte la descripción de la imagen aquí

¿Por qué tiene que cerrar la transmisión o ejecutar el vaciado antes de escribir datos?

La razón es que después de ejecutar close, FileWriter en realidad llamará a la interfaz subyacente para la escritura de datos.

inserte la descripción de la imagen aquí

Flujo de nodo y flujo de proceso

concepto

Flujo de nodo: puede leer y escribir datos de una fuente de datos específica (archivo), como el anterior FileInputStream, FileWriter

Flujo de proceso: según el flujo existente, proporcione funciones de lectura y escritura más potentes para el programa, es decir, use el patrón de diseño del decorador para expandir la función del flujo original y hacerlo más potente, como BufferedReader, BufferedWriter

Principio de flujo de proceso

¿Por qué el flujo de procesamiento puede encapsular el flujo del nodo original?Tome BufferedWriter como ejemplo

FileWriter hereda la clase Writer y BufferedWriter también hereda la clase Writer

inserte la descripción de la imagen aquí

El tipo de datos del atributo de miembro fuera de BufferedWriter es el objeto que Writer puede recibir FilerWriter, que es la encarnación del polimorfismo. Esto muestra que podemos encapsular cualquier flujo de nodo, siempre que el objeto de flujo de nodo sea una subclase de Writer, y lo mismo es cierto para BufferedReader.

inserte la descripción de la imagen aquí

flujo de procesamiento

La función de los flujos de procesamiento se refleja principalmente en los siguientes dos aspectos:

  1. Mejora del rendimiento: principalmente aumentando el almacenamiento en búfer para mejorar la eficiencia de entrada y salida.
  2. Conveniencia de operación: el flujo de procesamiento puede proporcionar una serie de métodos convenientes para ingresar y generar una gran cantidad de datos a la vez, como su propio búfer, lo que mejora el rendimiento de lectura y es más flexible y conveniente de usar.

BufferedReader

API relacionadas

inserte la descripción de la imagen aquí

ejemplo de código

Al crear un objeto BufferedReader, debe pasar el objeto de flujo de nodo correspondiente y cerrar el flujo externo. Llamar al método de cierre de BufferedReader también llamará al método de cierre del flujo de nodo para cerrar el flujo.

String filePath = "d:\\IOTest\\note.txt";
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
String line = "";
//按行读取效率高,返回null时表示读取完成
while((line=bufferedReader.readLine())!=null){
    
    
    System.out.println(line);
}
//关闭外层流即可
bufferedReader.close();

BufferedWriter

API relacionadas

inserte la descripción de la imagen aquí

ejemplo de código

String filePath = "d:\\IOTest\\ok.txt";
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
bufferedWriter.write("hello,你好世界~");
bufferedWriter.newLine();//系统换行
bufferedWriter.write("hello,你好~");
bufferedWriter.newLine();
bufferedWriter.write("hello,你好世界~");
bufferedWriter.newLine();
bufferedWriter.close();

inserte la descripción de la imagen aquí

BufferedOutputStream y BufferedInputStream

BufferedInputStream: flujo de bytes, al crear BufferedInputStream creará automáticamente una matriz de búfer, es decir, no necesitamos crear manualmente un búfer

BufferedOutputStream: secuencia de bytes, que implementa una secuencia de salida almacenada en búfer, puede escribir varios bytes en la secuencia de salida subyacente sin tener que llamar al sistema subyacente para cada escritura de byte

flujo de procesamiento de objetos

usar

Cuando necesitamos guardar su tipo al guardar datos y restaurar el objeto o el tipo de datos en el archivo, debemos poder serializar y deserializar el tipo de datos u objeto básico. En este momento, necesitamos usar el flujo de procesamiento de objetos. Realizar manipulación de datos

Serialización y deserialización

Serialización: La serialización es guardar el valor y el tipo de datos de los datos al guardar los datos

Deserialización: La deserialización es restaurar el valor y el tipo de datos de los datos al restaurar los datos

Condiciones para realizar la serialización

Para lograr la serialización, una clase debe implementar la interfaz Serializable, y todas las clases contenedoras de los tipos de datos básicos de Java implementan la interfaz Serializable.

ObjectOutputStreamObjectOutputStream

API relacionadas

Se proporcionan una serie de API para facilitarnos la salida de tipos de datos básicos y clases personalizadas.

inserte la descripción de la imagen aquí

ejemplo de código
 public static void main(String[] args) throws Exception{
    
    
        String filePath = "d:\\IOTest\\data.dat";
        ObjectOutputStream oos =
                new ObjectOutputStream(new FileOutputStream(filePath));
        oos.writeInt(100);
        oos.writeBoolean(true);
        oos.writeChar('a');
        oos.writeDouble(9.5);
        oos.writeUTF("jack");
        oos.writeObject(new Dog("旺财",10));
        oos.close();
        System.out.println("数据保存完毕(序列化形式)");
    }

}
class Dog implements Serializable {
    
    
    private String name;
    private int age;

    public Dog(String name, int age) {
    
    
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
    
    
        return "Dog{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

Debido a que es un flujo de bytes, está distorsionado porque no se ha convertido en una codificación, pero aún podemos ver que el tipo es Dog

inserte la descripción de la imagen aquí

ObjetoEntradaStream

API relacionadas

inserte la descripción de la imagen aquí

ejemplo de código

String filePath = "d:\\IOTest\\data.dat";
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
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());
Object dog = ois.readObject();
System.out.println("运行类型为:"+dog.getClass());
System.out.println(dog);
ois.close();
System.out.println();

inserte la descripción de la imagen aquí

flujo de conversión

necesidad

Cuando leemos un archivo a través de FileInputStream, cuando leemos chino, habrá caracteres ilegibles, como se muestra en la figura, se convertirán en caracteres ilegibles, por lo que debemos convertir la secuencia para especificar el formato de codificación.

inserte la descripción de la imagen aquí

InputStreamReader

InputStreamReader, como una subclase de Reader, puede envolver InputStream (flujo de bytes) en (convertir) Reader (flujo de caracteres)

Constructor y API

La característica más importante es que podemos especificar el formato de codificación de la transmisión.

inserte la descripción de la imagen aquí

ejemplo de código

String filePath = "d:\\IOTest\\note.txt";
//创建输入转化流InputStreamReader对象,同时指定编码为utf-8
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(filePath), "utf-8");
//包装成BufferedReader对象进行字符读取操作
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String s = bufferedReader.readLine();
System.out.println("读取内容="+s);
bufferedReader.close();

Podemos ver otro gran dinero

inserte la descripción de la imagen aquí

OutputStreamWriter

OutputStreamWriter: una subclase de Writer, que realiza el empaquetado de OutputStream (flujo de bytes en Writer).

Métodos de construcción y API relacionadas

inserte la descripción de la imagen aquí

ejemplo de código

String filePath = "d:\\IOTest\\hello.txt";
//指定编码
String charSet="utf8";
//包装流
OutputStreamWriter outputStreamWriter =
        new OutputStreamWriter(new FileOutputStream(filePath), charSet);
outputStreamWriter.write("hello world 你好世界");
outputStreamWriter.close();
System.out.println("按照 "+charSet+" 保存文件成功~");

inserte la descripción de la imagen aquí

flujo de impresión

PrintStream y PrintWriter

API relacionadas

PrintStream imprime el contenido en la pantalla de forma predeterminada, pero podemos especificar la ubicación de salida a través del constructor, como enviar el contenido a un archivo

inserte la descripción de la imagen aquí

ejemplo de código

PrintStream out = System.out;
out.print("john,hello");
out.write(" 你好".getBytes());
out.close();
//修改输出位置
System.setOut(new PrintStream("d:\\f1.txt"));
System.out.println("hello,你好世界");







Supongo que te gusta

Origin blog.csdn.net/weixin_64133130/article/details/132125747
Recomendado
Clasificación