07.IO流

news2024/12/25 14:28:19

07. IO流

01. 文件

1. 什么是文件

​ 文件对我们并不陌生,文件是保存数据的地方,比如大家经常使用的word文档,txt文件,excel文件…都是文件。它既可以保存一张图片,可以保存视频,声音

2.文件流

​ 文件在程序中是以流的形式来操作的
在这里插入图片描述

  1. :数据在数据源(文件)和程序(内存)之间的经历的路径
    2. 输入流:数据从数据源(文件)到程序(内存)的路径
    3. 输出流:数据从程序(内存)到数据源(文件)的路径

02. 常用的文件操作

1. 创建文件对象相关构造器和方法

1. 相关方法:
  1. new File(String pathname)//根据路径构建一个File对象
  2. new File(File parent, String child)//根据父目录文件+子路径构建
  3. new File(String parent, String child)//根据父目录+子路径构建
  4. createNewFile 创建新文件
2. 应用案例

要求:在E盘下,创建文件 news1.txt news2.txt news3.txt

import jdk.jfr.StackTrace;
import org.junit.jupiter.api.Test;

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


public class FileCreate {
    public static void main(String[] args) {

    }
    @Test
    //1. 方式一:new File(String pathname)
    public void create01() {
        String filePath = "e:\\news1.txt";
        File file = new File(filePath);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    //2. 方式二:new File(File parent, String child)//根据父目录文件+子路径构建
    public void creat02() {
        File file = new File("e:\\");
        String fileName = "news2.txt";
        File file1 = new File(file, fileName);
        try {
            file1.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    @Test
    //3. 方式三:new File(String parent, String child)//根据父目录+子路径构建
    public void creat03() {
        String parentPath = "e:\\";
        String childPath = "news3.txt";
        File file = new File(parentPath, childPath);
        try {
            file.createNewFile();
            System.out.println("文件创建成功");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2. 获取文件的相关信息

1. 方法

​ getName、getAbsolutePath、getParent、Length、exists、isFile、isDirectory

2. 应用案例
import java.io.File;

public class FileInformation {
    public static void main(String[] args) {

    }
    @Test
    //1. 获取文件的信息
    public void inf() {
        //1.1 先创建文件对象
        File file = new File("e:\\news1.txt");
        //1.2 调用相应的方法,得到对应的信息
        //1.3getName、getAbsolutePath、getParent、Length、exists、isFile、isDirectory
        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());

    }
}

3. 目录的操作和文件删除

1. 方法

mkdir创建一级目录,mkdirs创建多级目录,delete删除空目录或文件

2. 应用案例
package com.yzjedu.file;

import org.junit.jupiter.api.Test;

import java.io.File;

/**
 * 03. 目录的操作和文件删除
 **/
public class Directory_ {
    public static void main(String[] args) {

    }
    @Test
    //1.判断 e:\\news1.txt 是否存在,如果存在就删除
    public void m1() {
        String filePath = "e:\\news1.txt";
        File file = new File(filePath);
        if (file.exists()) {
            if (file.delete()) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败");
            }
        }else {
            System.out.println("文件不存在");
        }
    }
    @Test
    //2. 判断e:\\demo02 是否存在,存在就删除,否则提示不存在
    //体会,在java编程中,目录也被当做一种文件存在
    public void m2() {
        String filePath = "e:\\demo02";
        File file = new File(filePath);
        if (file.exists()) {
            if (file.delete()) {
                System.out.println("删除成功");
            } else {
                System.out.println("删除失败");
            }
        }else {
            System.out.println("该目录不存在");
        }
    }
    @Test
    //3. 判断e:\\demo\\a\\b\\c 目录是否存在,如果存在就提示已经存在,否则就创建
    public void m3() {
        String directoryPath = "e:\\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("创建失败");
            }
        }
    }
}

03. Java IO流原理及流的分类

1. Java IO流原理

  1. I/O是Input/Output的缩写,I/O技术是非常实用的技术, 用于处理数据传输。如读/写文件,网络通讯等。
  2. Java程序中,对于数据的输入/输出操作以”流(stream)"的方式进行。
  3. java.io包下提供了各种“流"类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
  4. 输入input: 读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中。
  5. 输出output: 将程序(内存)数据输出到磁盘、光盘等存储设备中

2. 流的分类

  1. 按操作数据单位不同分为: 字节流(8 bit) 二进制文件, 字符流(按字符) 文本文件
  2. 按数据流的流向不同分为: 输入流,输出流
  3. 按流的角色的不同分为:节点流,处理流/包装流
(抽象基类)字节流字符流
输入流InputStreamReader
输出流OutputStreamWriter
  1. Java的I0流共涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生的。
  2. 由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。

3. 流和文件的区别

  1. 流是数据的抽象和传输方式,而文件是数据的存储形式。
  2. 流是实时的、动态的,而文件是静态的、持久的。
  3. 流通常用于数据的临时传输和处理,而文件用于长期存储和持久化。

04. IO体系-常用的类

1. InputStream(字节输入流)

​ InputStream抽象类是所有类字节输入流的超类

2. InputStream常用的子类

  1. FileInputStream: 文件输入流
  2. BufferedInputStream:缓冲字节输入流
  3. ObjectInputStream:对象字节输入流

3. FileInputStream应用实例

**要求:**使用FileInputStream 在 a.txt文件,写入“hello,world”,如果文件不存在,会创建文件(注意:前提是目录已经存在)

import org.junit.jupiter.api.Test;

import java.io.FileInputStream;
import java.io.IOException;

public class FileInputStream_ {
    public static void main(String[] args) {

    }

    /**
     * 演示读取文件
     */
    @Test
    public void readFile01() {
        String filePath = "d:\\hello.txt";
        FileInputStream fileInputStream = null;
        //2. 字节数组
        byte[] buf = new byte[8];//2.1 一次读取8个字节
        int readLen = 0;

        try {
            //1. 创建 FileInputStream 对象,用于读取文件
            fileInputStream = new FileInputStream(filePath);
            //1.1 从改输入流读取一个字节的数据。如果没有输入可用,此方法将阻止
            //1.2 如何返回-1,表示读取完毕
            //2.2 如果读取正常,返回实际读取的字节数
            while ((readLen = fileInputStream.read(buf)) != -1) {
               System.out.print(new String(buf, 0, readLen));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        finally {
            //1.3 关闭文件,释放资源
            try {
                fileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

4. FileOutputStream

1. 介绍

​ 该类的主要作用是创建一个输出流,使程序能够将数据写入文件。通过 FileOutputStream 类,可以逐字节地将数据写入文件,也可以一次性写入字节数组。

2. FileOutputStream应用实例1

​ 要求: 请使用 FileOutputStream 在 a.txt 文件,中写入 “hello,world”, 如果文件不存在,会创建 文件(注意:前提是目录已经存在.)

import org.junit.jupiter.api.Test;

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

public class FileOutputStream01 {
    public static void main(String[] args) {

    }

    /**
     * 演示使用FileOutputStream 将数据写到文件中
     * 如果文件不存在,则创建该文件
     */
    @Test
    public void writeFile() {
        //1. 创建 FileOutputStream 对象
        String filePath = "d:\\a.txt";
        FileOutputStream fileOutputStream = null;


        try {
            //1.1 得到FileOutputStream对象
            //2. new FileOutputStream(filePath) 创建方式,当写入内容时,会覆盖原来的内容
            //2.1 new FileOutputStream(filePath, true) 创建方式,当写入入内容时,会增加到文件的末尾
            fileOutputStream = new FileOutputStream(filePath, true);
            //1.2 写入一个字节
//            fileOutputStream.write('H');
            //1.3 写入字符串
            String str = "hello,world!";
            //getBytes() 这个方法的作用可以把 字符串 -> 字节数组
//            fileOutputStream.write(str.getBytes());
            //1.4 write(byte[] b, int off, int len) 方法二
            fileOutputStream.write(str.getBytes(), 0, /*str.length()将所有的字符串内容写入*/ 3);
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
3. FileOutputStream应用实例2

​ 要求:编程完成图片/音乐的拷贝

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

public class FileCopy {
    public static void main(String[] args) {
        //1. 完成文件拷贝,将d:\\pg.png 拷贝 c:\\
        //2. 思路分析
        //2.1 创建文件的输入流,将文件读入到程序
        //2.2 创建文件的如初六,将读取到的文件数据,写入到指定的文件
        String srcFilePath = "d:\\bg.png";
        String destFilePath = "d:\\bg2.png";
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            fileInputStream = new FileInputStream(srcFilePath);
            fileOutputStream = new FileOutputStream(destFilePath);
            //3. 定义一个字节数组,提高读取效果
            byte[] buf = new byte[1024];
            int readLen = 0;
            while ((readLen = fileInputStream.read(buf)) != -1) {
                //3.1 读取到后,就写入到文件,通过 fileOutputStream
                //3.2 即 边读边写
                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();
            }
        }
    }
}

5. FileReader和FileWriter

1. 介绍
FileReader

作用: FileReader 用于读取字符文件中的数据。
特点: 它是从文件中读取字符数据的便捷类,通常与 BufferedReader 结合使用,以提高读取效率。
构造方法:
FileReader(File file):根据指定的文件创建一个新的 FileReader。
FileReader(String fileName):根据指定的文件名创建一个新的 FileReader。

FileWriter

作用: FileWriter 用于向文件中写入字符数据。
特点: 它是从文件中写入字符数据的便捷类,通常与 BufferedWriter 结合使用,以提高写入效率。
构造方法:
FileWriter(File file):根据指定的文件创建一个新的 FileWriter。
FileWriter(String fileName):根据指定的文件名创建一个新的 FileWriter。

2. FileReader常用方法
  1. new FileReader(File/String)
  2. read: 每次读取单个字符,返回该字符,如果到文件未尾返回-1
  3. read(char[]): 批量读取多个字符到数组,返回读取到的字符数,如果到文件未尾返回-1
    相关API:
  4. new String(char[]): 将char[]转换成String
  5. new String(char[],off,len): 将char[]的指定部分转换成String
3. FileWriter常用方法
  1. new FileWriter(File/String):覆盖模式,相当于流的指针在首端
  2. new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
  3. write(int):写入单个字符
  4. write(char[]):写入指定数组
  5. write(char[],off,len):写入指定数组的指定部分
  6. write (string) :写入整个字符串
  7. write(string,off,len):写入字符串的指定部分
    相关API:String类: toCharArray:将String转换成char[]
    注意:FileWriter使用后,必须要关闭(close)或刷新(flush), 否则写入不到指定的文件!
4. FileReader和FileWriter应用案例
要求:
  1. 使用FileReader从story.txt 读取内容,并显示
import org.junit.jupiter.api.Test;

import java.io.FileReader;
import java.io.IOException;


public class FileReader_ {
    public static void main(String[] args) {

    }

    /**
     * 单个字符读取文件
     */
    @Test
    public void readFile01() {
        String filePath = "d:\\story.txt";
        FileReader fileReader = null;
        int data = 0;
        //1. 创建FileReader对象
        try {
            fileReader = new FileReader(filePath);
            //2. 循环读取 使用read, 单个字符读取
            while ((data = fileReader.read()) != -1) {
                System.out.print((char)data);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
    *多个字符读取文件
    */
    @Test
    public void readFile02() {
        String filePath = "d:\\story.txt";
        FileReader fileReader = null;
        int readLen = 0;
        char[] buf = new char[8];

        //1. 创建FileReader对象
        try {
            fileReader = new FileReader(filePath);
            //2. 循环读取 使用read, 8个字符读取
            while ((readLen = fileReader.read(buf)) != -1) {
                System.out.print(new String(buf, 0, readLen));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
  1. 使用 FileWriter 将 “风雨之后,定见彩虹” 写入到 note.txt 文件中, 注意细节
import java.io.FileWriter;
import java.io.IOException;


public class FileWriter_ {
    public static void main(String[] args) {
        String filePath = "d:\\note.txt";
        FileWriter fileWriter = null;
        char[] chars = {'a', 'b', 'c'};
        try {
            fileWriter = new FileWriter(filePath);
//            3.  write(int):写入单个字符
            fileWriter.write('h');
//            4.  write(char[]):写入指定数组
            fileWriter.write(chars);
//            5.  write(char[],off,len):写入指定数组的指定部分
            fileWriter.write("加油加油", 0, 3);
//            6.  write (string) :写入整个字符串
            fileWriter.write(" 你好,我来了");
            fileWriter.write("风雨之后,定见彩虹");//完成要求
//            7.  write(string,off,len):写入字符串的指定部分
            fileWriter.write("真的是好像吃饭", 0, 3);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //8. 对于FileWriter, 一定要关闭流,或者flush才能真正把数据写入到文件
            try {
                fileWriter.flush();
              //fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("程序结束");
    }
}

05. 节点流和处理流

1. 基本介绍

1. 节点流:

​ 节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter
想象一下你需要从一个水源中直接取水。节点流就像是直接与数据源连接的水龙头,它们直接读取或写入数据到数据源。
​ 在Java中,节点流直接与文件、网络连接或内存数据相连,可以实现基本的读写操作。

2. 处理流

​ 处理流(也叫包装流)是"连接”在已存在的流(节点流或处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如BufferedReader/BufferedWriter
​ 现在想象一下你在取水时使用了一个过滤器或者水桶来处理水流。处理流就像是对节点流的增强,它们提供了更高级别的功能和操作。
​ 处理流不直接与数据源相连,而是对节点流进行包装,并提供了缓冲、转换、过滤等功能。

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

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

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

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

4. 处理流-BufferedReader和BufferedWriter

1. BufferedReader应用案例

要求:使用BufferedReader读取文本文件,并显示在控制台

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;

public class BufferedReader_ {
    public static void main(String[] args) throws Exception {
        String filePath = "d:\\a.txt";
        //1. 创建BufferedReader
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
        //2. 读取
        String line;//2.1 按行读取
        //说明:
        //1. bufferedReader.readLine();按行读取文件
        //2. 当返回null时,表示文件读取完毕
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }
        //关闭流,这里注意,只需要关闭 BufferedReader,因为底层会自动去关闭 节点流
        bufferedReader.close();
    }
}
2. BufferedWriter应用案例

要求使用BufferedWriter将“你好,我可以进来吗”,写入到文件中

import java.io.*;

public class BufferWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath = "d:\\a.txt";
        //创建BufferedWriter对象
        //说明:
        //1. new FileWriter(filePath, true) 表示以追加的方式写入
        //2. new FileWriter(filePath) 表示已覆盖的方式写入
        BufferedWriter bufferedWriter = null;
        bufferedWriter = new BufferedWriter(new FileWriter(filePath,true));
        bufferedWriter.write("你好,我可以进来吗");
        bufferedWriter.newLine();
        bufferedWriter.write("你好,我可以进来吗");
        bufferedWriter.newLine();
        bufferedWriter.write("你好,我可以进来吗");
        //插入一个换行

        //说明关闭外层流即可,传入的new FileWriter(filePath),会在底层关闭
        bufferedWriter.close();


    }
}
3. 综合案例

要求:综合使用BufferedReader和BufferedWriter完成文本文件的拷贝,注意文件编码

import java.io.*;

public class BufferedCopy_{
    public static void main(String[] args) {
        String srcFilePath = "d:\\a.txt";
        String destFilePath = "d:\\a2.txt";
        BufferedReader bufferedReader = null;
        BufferedWriter bufferedWriter = null;
        //说明:
        //1. BufferedReader和BufferedWriter是安装字符操作
        //2. 不要操作二进制文件,可能造成文件损坏

        try {
            bufferedReader = new BufferedReader(new FileReader(srcFilePath));
            bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));
            String Line;
            //1. 读取文件内容
            while ((Line = bufferedReader.readLine()) != null) {
                //2. 每读取一行,就写入
                bufferedWriter.write(Line);
                //2.1 插入一个换行
                bufferedWriter.newLine();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (bufferedReader != null) {
                    bufferedReader.close();
                }
                if (bufferedWriter != null) {
                    bufferedWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

5. 处理流-BufferedInputStream 和 BufferedOutputStream

1. 介绍BufferedInputStream

​ BufferedInputStream是字节流,在创建BufferedInputStream时,会创建-个内部缓冲区数组.

2. 介绍bufferedOutputStream

​ BufferedOutputStream是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层

3. 应用案例

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

package com.yzjedu.outputstream_;

import java.io.*;

/**
 * @author Icaru
 * @version 1.0
 * @date 2024/3/3 20:58
 * 13.
 */
public class BufferedCopy02 {
    public static void main(String[] args) {
        String srcFilePath = "d:\\win.jpg";
        String destFilePath = "d:\\win2.jpg";

        //1. 创建BufferedInputStream对象和BufferedOutputStream对象
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            //因为 FileInputStream 是 InputStream的子类
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath));

            //2. 循环读取文件,并写入到 destFilePath
            byte[] buff = new byte[1024];
            int readLen = 0;
            while ((readLen = bis.read(buff)) != -1) {
                bos.write(buff, 0, readLen);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3. 关闭外层流即可,底层会自动关闭节点流
            try {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

6. 对象流-ObjectInputStream 和 ObjectOutputStream

1. 看一个需求
  1. 将int num = 100这个int数据保存到文件中,注意不是100数字,而是int 100,井且,能够从文件中直接恢复int 100
  2. 将Dog dog = new Dog(”小黄”,3)这个dog对象保存到文件中,并且能够从文件恢复.
  3. 上面的要求, 就是能够将基本数据类型或者对象进行序列化和反序列化操作
2. 序列化和反序列化
  1. 序列化就是在保存数据时, 保存数据的值数据类型
  2. 反序列化就是在恢复数据时,恢复数据的值数据类型
  3. 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
    Serializable // 这是一个标记接口,没有方法
    Externalizable //该接口有方法需要实现,因此我们一般实现上面的Serializable接口
3. 对象流介绍

​ 功能:提供了对基本类型的序列化和反序列化的方法
​ ObjectOutputStream 提供序列化功能
​ ObjectInputStream 提供反序列化功能

4. 应用案例
  1. 要求:使用ObjectOutputStream序列化基本数据类型和一个Dog对象(name, age), 并保存到data.dat文件中
import java.io.*;

public class ObjectOutputStream_ {
    public static void main(String[] args) throws IOException {
        //1. 序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
        String filePath = "d:\\data.dat";
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));

        //2. 序列化数据到 e:\data
        oos.write(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
        //保存一个对象
        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;
    }
}
  1. 使用ObjectInputStream读取data.dat并反序列化恢复数据
import com.yzjedu.outputstream_.Dog;

import java.io.*;

public class ObjectInputStream_ {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        //1. 制定反序列化的文件
        String filePath = "d:\\data.dat";
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath));
        //2. 读取(反序列化)的顺序需要和你保存数据(序列化)的顺序一致
        //2.1 否则会出现异常

        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());
        //3.2 dog 的编译类型是Object,dog运行类型是Dog
        Object dog = ois.readObject();
        System.out.println("运行类型" + dog.getClass());
        System.out.println("dog信息 = " + dog);

        //3. 这里是特别重要的细节:
        //3.1 如果我们希望调用Dog方法,需要向下转型
        //3.2 需要我们将Dog类的定义,拷贝到可以引用的位置
        Dog dog2 =(Dog)dog;
        System.out.println(((Dog) dog).getName());

        //关闭流, 只关闭外层流即可
        ois.close();
    }
}

**注意:**假如我们要反序列化,记得将上一个ObjectOutputStream_类中的Dog类移出,设置为public类,这样反序列化,就不会出现毛病

5. 注意事项和细节说明
  1. 读写顺序要一致
  2. 要求序列化或反序列化对象,需要实现Serializable
  3. 序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
//1.还记得我们的上个案例中的Dog类吗
//1.1 在它的属性中添加
 private static final long serialVersionUID = 1L;
//1.2 添加后就可以进行序列化和反序列化时,在Dog类中添加其他的属性不会影响其序列化(反序列化),提高了版本兼容性
  1. 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
  2. 序列化对象时,要求里面属性的类型也需要实现序列化接口
    1. 这句话的意思是,当你要将一个对象序列化成字节流保存到文件或者通过网络传输时,这个对象的所有属性都需要是可序列化的。也就是说,对象的属性类型必须要实现Serializable接口,否则在序列化过程中会抛出NotSerializableException异常
  3. 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化

7. 标准输入输出流

1. 介绍
类型默认设备
System.in 标准输入InputStream键盘
System.out 标准输出PrintStream显示器
2. 应用案例
  1. 传统方法System.out.println(“”); 是使用out对象将数据输出到显示器
  2. 传统方法,Scanner是从标准输入 键盘接受数据
import java.util.Scanner;

public class InputAndOutput {
    public static void main(String[] args) {
        //1. System 类 的 public final static InputStream in = null;
        //1.1 System.in 编译类型 InputStream
        //1.2 System.in 运行类型 BufferedInputStream
        //1.3 表示是标准输入 键盘
        System.out.println(System.in.getClass());

        //2. public final static PrintStream out = null;
        //2.1 编译类型 PrintStream
        //2.2 运行类型 PrintStream
        //2.3 表示标准输出 显示器
        System.out.println(System.out.getClass());

        System.out.println("hello,world!");
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入内容:");
        String next = scanner.next();
        System.out.println(next);

    }
}

8. 转换流-InputStreamReader 和 OutputStreamWriter

1. 引出问题

​ 在前面的内容中我们经常见到创建的文件有乱码问题,那么我们该如何解决乱码问题,这就要引出转换流。让我们先写一段代码,看看乱码的问题

import java.io.*;

public class CodeQuestion {
    public static void main(String[] args) throws IOException {
        /*
        看一个乱码问题
     */
        //1. 创建字符输入流 BufferedReader [处理流]
        //2. 使用 BufferedReader 对象读取 a.txt
        //3. 默认情况下,读取文件是按照 utf-8 编码
        //4. 如果你将文件修改为其他编码例如国标码,你会发现文件出现乱码
        String filePath = "d:\\a.txt";
        BufferedReader br = new BufferedReader(new FileReader(filePath));
        String s = br.readLine();
        System.out.println("读取到的内容是:" + s);
        br.close();
    }
}
2. 介绍
  1. InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成(转换)Reader(字符流)
  2. OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
  3. 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
  4. 可以在使用时指定编码格式(比如utf-8, gbk,gb2312, IS08859-1等)
3. 应用案例
  1. 编程将字节流FilelnputStream 包装成(转换成)字符流InputStreamReader,对文件进行读取(按照utf-8/gbk格式),进而在包装成BufferedReader
import java.io.*;

public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {
        String filePath = "d:\\a.txt";
        //解读
        //1. 把FileInputStream 转成 InputStreamReader
        //2. 指定编码 gbk
        //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
        //3. 把InputStreamReader 传入 BufferedReader
        //BufferedReader br = new BufferedReader(isr);

        //5. 一般情况下我们可以将2 和 3 结合起来
        BufferedReader br = new BufferedReader(new InputStreamReader(
                new FileInputStream(filePath),"gbk"));

        //4. 读取
        String s = br.readLine();
        System.out.println("读取内容= " + s);
        br.close();

    }
}
  1. 编程将字节流FileOutputStream 包装成(转换成) 字符流OutputStreamWriter,对文件进行写入(按照gbk格式,可以指定其他,比如utf-8)
import com.yzjedu.writer_.BufferWriter_;

import java.io.*;

/**
 * 演示 OutputStreamWriter 使用
 * 把FileOutputStream 字节流,转成 OutputStreamWriter
 * 指定处理的编码 gbk/utf-8/utf8
 */
public class OutputStreamWriter {
    public static void main(String[] args) throws IOException {
        String filePath = "d:\\a.txt";
        String charSet = "utf-8";
        BufferedWriter osw = new BufferedWriter(new java.io.OutputStreamWriter(
                new FileOutputStream(filePath), charSet));
        osw.newLine();
        osw.write("你好,hello!");
        osw.close();
        System.out.println("按照 " + charSet + " 保存文件成功");


    }
}

9. 打印流-PrintStream和PrintWriter

1. 介绍

​ 打印流(PrintStream和PrintWriter)是Java中的输出流类,它们使得将数据输出到文件、控制台或网络等目标变得更加简单。PrintStream用于处理字节流数据,而PrintWriter则处理字符流数据。
**注意:**打印流只有输出流,没有输入流

2. 应用实例
  1. PrintStream案例
import java.io.IOException;
import java.io.PrintStream;

public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        PrintStream out = System.out;
        //1. 在默认情况下,PrintStream输出数据的位置是 标准输出,即显示器
        /*
        public void print(String s) {
            if (s == null) {
                s = "null";
            }
            write(s);
        }
         */
        out.print("java,i like");
        //1.1 因为print的底层使用的是Write,所以我们可以直接调用write进行打印/输出
        out.write("lmf,你好".getBytes());

        //2. 我们可以去修改打印流输出的位置/设备
        //2.1 输出修改成了"d:\\f1.txt"
        //2.2 "hello, lmf" 会打印到f1.txt的位置
        System.setOut(new PrintStream("d:\\f1.txt"));
        System.out.println("hello, lmf");
    }
}
  1. PrintWriter案例
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;

public class PrintWrite_ {
    public static void main(String[] args) throws IOException {
//        PrintWriter printWriter = new PrintWriter(System.out);
        PrintWriter printWriter = new PrintWriter(new FileWriter("d:\\f2.txt"));
        printWriter.print("hi, 天津你好");
        printWriter.close();//注意要记得关闭,如果没有关闭,不会输出
    }
}

10. Properties类

1. 看一个需求

如下一个配置文件 mysql.properties
ip: 192.168.0.13
ueser=root
pwd=12345

请问编程读取ip、user和pwd的值是多少

分析
  1. 传统方法
import javax.sound.sampled.Line;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class Properties01 {
    public static void main(String[] args) throws IOException {
        //1. 读取mysql.properties 文件,并得到ipk, user 和 pwd
        BufferedReader bufferedReader = new BufferedReader(
                new FileReader("src\\mysql.properties"));
        String line = "";
        while ((line = bufferedReader.readLine()) != null) {//循环读取
            String[] parts = line.split("=");
            System.out.println(parts[0] + "值是:" + parts[1]);
        }
    }
}

如果我们只取ip,我们还要手动去写"ip".equals(split[0]) 判断,比较麻烦

2. 基本介绍
  1. 专门用于读写配置文件的集合类
    配置文件的格式:
    键=值
    键=值
  2. 注意:键值对不需要有空格,值不需要用引号括起来。默认类型是String
  3. Properties的常用方法
    1. load:加载配置文件的键值对到Properties对象
    2. list:将数据显示到指定设备/流对象
    3. getProperty(key):根据键获取值
    4. setProperty(key,value):设置键值对到Properties对象
    5. store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
3. 应用案例
  1. 使用Properties类完成对mysql.properties的读取
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

/**
 * 演示Properties类 来读取mysql.properties
 */
public class Properties02 {
    public static void main(String[] args) throws IOException {

        //1. 创建Properties 对象
        Properties properties = new Properties();
        //2. 加载到指定的文件
        properties.load(new FileReader("src\\mysql.properties"));
        //3. 把k-v显示控制台
        properties.list(System.out);
        //4. 根据key 获取对应的值
        String user = properties.getProperty("user");
        String pwd = properties.getProperty("pwd");
        System.out.println("user的值是" + user);
        System.out.println("pwd的值是" + pwd);
    }
}
  1. 使用Properties类添加key-val 到新文件mysql2.properties 中
  2. 使用Properties类完成对mysql2.properties的读取,并修改某个key-val
/**
  * 演示Properties 类来配置文件,修改配置文件的内容
 */
public class Properties03 {
    public static void main(String[] args) throws IOException {
        Properties properties = new Properties();
        //创建
        //1. 如果该文件没有key 就是创建
        //2. 如果该文件有key 就是修改
        //3. Properties 父类是 Hashtable底层就是Hashtable的核心方法
        properties.setProperty("charset", "utf-8");
        properties.setProperty("user","江南");//注意保存时,中文是unicode码值
        properties.setProperty("pwd","bdhs");

        //将k-v存储到一个文件
        properties.store(new FileOutputStream("src\\mysql2.properties"),"hello"/*这是一个注释,可以为空*/);
        System.out.println("保存配置文件成功");
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1489311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【STA】多场景时序检查学习记录

单周期路径 建立时间时序检查 在时钟的有效沿到达触发器之前,数据应在一定时间内保持稳定,这段时间即触发器的建立 时间。满足建立时间要求将确保数据可靠地被捕获到触发器中。 建立时间检查是从发起触发器中时钟的第一个有效沿到捕获触发器中时钟后面…

【OJ】求和与计算日期

文章目录 1. 前言2. JZ64 求123...n2.1 题目分析2.2 代码 3. HJ73 计算日期到天数转换3.1 题目分析3.2 代码 4. KY222 打印日期4.1 题目分析4.2 代码 1. 前言 下面两个题目均来自牛客,使用的编程语言是c,分享个人的一些思路和代码。 2. JZ64 求123…n …

117.移除链表元素(力扣)

题目描述 代码解决 class Solution { public:ListNode* removeElements(ListNode* head, int val) {//删除头节点while(head!NULL&&head->valval){ListNode*tmphead;headhead->next;delete tmp;}//删除非头节点ListNode*curhead;while(cur!NULL&&cur-&g…

阿里云国际云解析DNS如何开启/关闭流量分析?

流量分析服务会涉及产生日志费用,所以开通内网DNS解析服务后,默认不会主动开启流量分析,需要您手动开启流量分析。对于未开启流量分析的用户,进入界面会提示您展示的都是模拟数据,您可以点击开启流量分析服务&#xff…

Vue+SpringBoot打造城市桥梁道路管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询城市桥梁4.2 新增城市桥梁4.3 编辑城市桥梁4.4 删除城市桥梁4.5 查询单个城市桥梁 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的城市桥梁道路管理系统,支持…

(十六)【Jmeter】取样器(Sampler)之测试活动(Test Action)

简述 操作路径如下: JMeter中的测试活动取样器实际上并不是一个具体的取样器类型,而是一种对测试计划中的多个取样器进行组合和执行的活动。常常被用作定时器,在某个请求之后等待多长时间。 参数说明 Logical Action on Thread(在线程上的逻辑操作) Pause Duration(mil…

“羊驼“入侵CV,美团浙大沈春华团队将LLaMA向CV扩展,构建全新基础模型VisionLLaMA

本文首发:AIWalker https://arxiv.org/abs/2403.00522 https://github.com/Meituan-AutoML/VisionLLaMA 本文概述 大型语言模型构建在基于Transformer的架构之上来处理文本输入, LLaMA 系列模型在众多开源实现中脱颖而出。类似LLaMa的Transformer可以用来处理2D图像吗&#xf…

关于数据库基本概念与基本介绍

​ 数据库是 一个组织良好的数据集合,旨在方便多个用户高效地共享信息资源 。以下是关于数据库的一些基本介绍: 1. 定义和目的:数据库是一个电子化的数据存储系统,设计用来存储、管理和检索数据。它允许用户或应用程序以各种复杂的…

【代码随想录算法训练营Day35】435.无重叠区间;763.划分字母区间;56.合并区间

文章目录 ❇️Day 36 第八章 贪心算法 part05✴️今日任务❇️435. 无重叠区间自己的思路自己的代码(✅通过81.59%)随想录思路随想录代码 ❇️763.划分字母区间自己的思路自己的代码(✅通过55.30%)随想录思路随想录代码 ❇️56. 合…

计算机网络-网络安全(二)

1.应用层安全协议: S-HTTP或SHTTP(Sec HTTP),安全超文本传输协议,是HTTP扩展,使用TCP的80端口。HTTPS:HTTPSSL,使用TCP的443端口。和TLS(传输层安全标准)是双…

Linux 安装 Mysql 8.0

获取 Mysql 8.0 在 /usr/local下 创建mysql文件夹 mkdir mysql切换到mysql文件夹下 cd mysql下载mysql wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz解压mysql tar xvf mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz重命名…

CSS技巧:实现两个div在同一行显示的方法

css如何让两个div在同一行显示 - web开发 - 亿速云 在Web开发中,经常遇到需要将多个元素水平排列在同一行的情况。其中一个常见的需求是将两个div元素放置在同一行上,使它们并排显示。在本文中,我们将介绍几种实现这一效果的CSS方法。 1. 使…

网络学习:SMart link技术与Monitor link技术

目录 一、SMart link技术 1.1、SMart link技术简介 1.2、SMart link技术原理及基础知识点 1、应用场景(举例): 2、运行机制 3、保护vlan 4、控制VLAN 5、Flush报文 6、SMart link的负载分担机制 7、SMart link角色抢占模式 二、Mo…

MySQL的Redo Log、Undo Log、Binlog与Replay Log日志

前言 MySQL数据库作为业界最流行的开源关系型数据库之一,其底层实现涉及多种重要的日志机制,其中包括Redo Log、Undo Log、Binlog和Replay Log。这些日志组件共同确保MySQL数据库系统在面对事务处理、数据恢复和主从复制等方面表现出色。本文主要介绍一下…

08 OpenCV 腐蚀和膨胀

文章目录 作用算子代码 作用 膨胀与腐蚀是数学形态学在图像处理中最基础的操作。其卷积操作非常简单,对于图像的每个像素,取其一定的邻域,计算最大值/最小值作为新图像对应像素位置的像素值。其中,取最大值就是膨胀,取最小值就是腐…

就业班 2401--3.4 Linux Day10--软件管理

一、软件管理 导语: 安装软件 rpm yum 源码安装 ​ 卸载软件 rpm介绍 rpm软件包名称: 软件名称 版本号(主版本、次版本、修订号) 操作系统 -----90%的规律 #有依赖关系,不能自动解决依赖关系。 举例:openssh-6.6.1p1-31.el7.x86_64.rpm 数字前面的是名…

SpringBoot多数据源配置(MySql、Oracle)

一、依赖 <!-- dynamic-datasource 多数据源--><dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId></dependency><!--oracle驱动--><dependency><groupI…

机器视觉——硬件选型

1、相机选型 在选择机器视觉相机时&#xff0c;通常需要考虑以下几个方面&#xff1a; 1、分辨率&#xff1a;相机的分辨率决定了其拍摄图像的清晰度和细节程度。根据具体的应用需求&#xff0c;可以选择适当的分辨率范围。 2、帧率&#xff1a;帧率表示相机每秒钟能够拍摄的…

linux无法启动dhcp服务--Failed to start DHCPv4 Server Daemon.错误

linux dhcp服务搭建详细过程请看 linux系统dhcp服务部署 关于dhcp服务无法启动Failed to start DHCPv4 Server Daemon.错误 解决方法&#xff1a;虚拟网络编辑器中的也就是dhcp所要服务的子网ip地址要与dhcp.conf中的服务网段ip一致&#xff08;与上面subnet 192.168.1.0一致…

伊理威科技:抖音上开店铺需要什么条件

在数字浪潮的推动下&#xff0c;抖音已成为连接品牌与消费者的新桥梁。若想在此平台开设小店&#xff0c;需满足一系列条件&#xff0c;方可乘风破浪。首要条件是拥有一张有效的身份证明或企业营业执照&#xff0c;这是验证商家身份和合法经营的基础。接着&#xff0c;商品质量…