Java File与IO流学习笔记

news2024/10/6 2:26:12

内存中存放的都是临时数据,但是在断电或者程序终止时都会丢失

而硬盘则可以长久存储数据,即使断电,程序终止,也不会丢失

File

  • Filejava.io.包下的类,File类的对象,用于代表当前操作系统的文件(可以是文件,或文件夹)
  • 可以获取文件信息(大小,文件名,修改时间)
  • 判断文件的类型
  • 创建文件或者文件夹
  • 删除文件或者文件夹…
  • 但是File类只能对文件本身进行操作,不能读写文件里面存储的数据
创建File对象
构造器说明
public File(String pathname)根据文件路径创建文件对象
public File(String parent,String child)根据父路径和子路径名字创建文件对象
public File(File parent,String child)根据父路径对应文件对象和子路径名字创建文件对象

案例

Main.java

import java.io.File;

public class Main {
    public static void main(String[] args) {
        // 创建一个File对象,指代某个具体的文件
        File file = new File("C:\\Users\\huihui\\Desktop\\test.txt");
        System.out.println(file); // C:\Users\huihui\Desktop\test.txt
        System.out.println(file.length()); // 文件大小 0
        File file1 = new File("C:/Users/huihui/Desktop/test.txt");
        System.out.println(file1); // C:\Users\huihui\Desktop\test.txt
        File file2 = new File("C:" + File.separator +"Users"+ File.separator + "huihui"+ File.separator + "Desktop"+ File.separator + "test.txt");
        System.out.println(file2); // C:\Users\huihui\Desktop\test.txt
    }
}

注意:File对象也可以指代一个不存在的文件路径

Main.java

import java.io.File;

public class Main {
    public static void main(String[] args) {
        File file = new File("aa/bb/cc");
        System.out.println(file.length()); // 0
        // 可以通过exists()方法判断文件是否存在
        System.out.println(file.exists()); // false
    }
}
路径
  • 路径分为绝对路径(带盘符)和相对路径(不带盘符)
import java.io.File;

public class Main {
    public static void main(String[] args) {
        // 据对路径,带盘符(是种写死的路径)
        File file = new File("D:\\Idea\\Codeing\\Day01\\src\\Demo\\Student.java");
        System.out.println(file); // D:\Idea\Codeing\Day01\src\Demo\Student.java
        // 相对路径,不带盘符(是种灵活的路径),默认回去当前工程下寻找文件
        File file1 = new File("src\\Demo\\Student.java");
        System.out.println(file1); // src\Demo\Student.java
    }
}
方法
判断文件类型,获取文件信息

在这里插入图片描述

案例

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.logging.SimpleFormatter;

public class Main {
    public static void main(String[] args) {
        File file = new File("C:\\Users\\huihui\\Desktop\\test.txt");
        // 1. exists() 文件是否存在
        System.out.println(file.exists()); // true
        // 2. isFile() 判断是否是文件
        System.out.println(file.isFile()); // true
        // 3. isDirectory() 判断是否是文件夹
        System.out.println(file.isDirectory()); // false
        // 4. getName() 获取文件的名称包括后缀
        System.out.println(file.getName()); // test.txt
        // 5. length() 获取文件大小,返回字节个数
        System.out.println(file.length()); // 0
        // 6. laseModified() 获取文件的最后修改时间,默认返回的是时间戳
        // System.out.println(file.lastModified()); // 1696232257337
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(sdf.format(file.lastModified())); // 2023-10-02 15:37:37
        // 7. getPath() 获取创建文件对象时,使用的路径(你写的是什么路径,它就会返回什么路径)
        System.out.println(file.getPath()); // C:\Users\huihui\Desktop\test.txt
        // 8. getAbsolutePath() 获取绝对路径
        System.out.println(file.getAbsolutePath()); // C:\Users\huihui\Desktop\test.txt
    }
}
创建或者删除文件

在这里插入图片描述

案例

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

public class Main {
    public static void main(String[] args) throws IOException {
        // 1. createNewFile() 创建一个新的文件,但是需要抛出异常。返回一个布尔值,如果存在,再创建就会返回false
        File file = new File("D:\\Idea\\Codeing\\Day01\\src\\Demo\\test.txt");
        System.out.println(file.createNewFile()); // true
        // 2. mkdir() 用于创建文件夹,但是只能创建一级文件夹。返回一个布尔值
        File f2 = new File("D:\\Idea\\Codeing\\Day01\\src\\Demo01");
        System.out.println(f2.mkdir()); // true
        // 3. mkdirs() 用于创建文件夹,可以创建多级文件夹
        File f3 = new File("D:/Idea/Codeing/Day01/src/Demo02/aa/bb");
        System.out.println(f3.mkdirs()); // true
        // 4. delete() 删除文件或者空文件,但是不能删除非空文件夹
    }
}
遍历文件夹

File类提供的遍历文件夹的功能

方法说明
public String[] list()获取当前目录下所有的“一级文件名称”,返回一个字符串数组
public File[] listFiles()获取当前目录下所有的“一级文件对象”,返回一个文件对象数组

使用listFiles注意事项:

  • 当主调是文件,或者路径不存在时,返回null
  • 当主调是空文件夹时,返回一个长度为0的数组
  • 当主调是一个有内容的文件夹时,将里面所有一级文件和文件夹的路径放在File数组中返回
  • 当主调是一个文件夹,且里面有隐藏文件时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
  • 当主调是一个文件夹,但是没有权限访问改文件夹时,返回null
import java.io.File;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        File file = new File("D:\\Idea\\Codeing\\Day01\\src\\Demo");
        // 1. public String[] list(): 获取当前目录下所有的 "一级文件名称"
        String[] list = file.list();
        System.out.println(Arrays.toString(list)); // [Student.java, test.txt]
        // 2. public File[] listFiles(): 获取当前目录下所有的 "一级文件对象"
        File[] files = file.listFiles();
        for (File file1 : files) {
            System.out.println(file1.isFile()); // true true
            System.out.println(file1.getAbsolutePath()); // 
        }
    }
}
递归

案例1:修改文件序号

import java.io.File;

public class Main {
    public static void main(String[] args) {
        // 改变某个文件夹下的文件的序号,要求从19开始
        File f = new File("C:\\Users\\huihui\\Desktop\\test");
        // 1. 得到里面所有的文件对象
        File[] files = f.listFiles();
        for (File file : files) {
            String name = file.getName();
            String start = name.substring(0, name.indexOf("."));
            String end = name.substring(name.indexOf("."));
            String newName = (Integer.valueOf(start) + 18) + end;
            // 开始改名
            file.renameTo(new File(f, newName));
        }
    }
}

递归就是方法调用自身,递归一定要有一个结束条件,不然会无限递归,造成栈内存溢出(因为方法会进入栈内,每次调用都会进栈,但是一直没有出来的话,栈内存中的方法就会越来越多,就会溢出)

递归形式:

  1. 直接递归:方法自己调用自己
  2. 间接递归:方法调用其他方法,其他方法又回调方法自己

直接递归:

public class Main {
    public static void main(String[] args) {
        print(0);
    }

    // 直接递归:方法内部直接调用自己
    public static void print(int num) {
        if(num < 10) {
            System.out.println("打印输出");
            print(++num);
        }
    }
}

间接递归:

public class Main {
    public static void main(String[] args) {
        print(0);
    }

    public static void print(int num) {
        temp(num);
    }
    // 间接递归:别的方法调用自己
    public static void temp(int num) {
        if(num < 10) {
            System.out.println("打印输出");
            print(++num);
        }
    }
}
求阶乘
public class Main {
    public static void main(String[] args) {
        System.out.println(print(5)); // 120
    }

    // 计算结阶乘
    public static int print(int num) {
        if(num == 1) return 1;
        return print((num - 1)) * num;
    }
}

在这里插入图片描述

求1-n的和
public class Main {
    public static void main(String[] args) {
        System.out.println(sum(5)); // 15
    }

    // 计算1-n的和
    public static int sum(int num) {
        if(num == 1) return 1;
        return sum(num - 1) + num;
    }
}
猴子吃桃

猴子第一天摘下若干桃子,当即吃了一般,觉得好不过瘾,于是又多吃了一个。第二天又吃了前天剩余桃子数量的一般,觉得好不过瘾于是又多吃了一个。以后每天都是吃昨天剩余桃子数量的一半加一个。到第十天就只剩一个桃子了。问猴子摘了多少桃子?

f(x) - f(x)/2 - 1 = f(x + 1) // 昨天吃的减去前天的一半再减1,就是今天的

public class Main {
    public static void main(String[] args) {
        System.out.println(sum(1)); // 1534
    }

    // 计算1-n的和
    public static int sum(int num) {
        if(num == 10) return 1;
        return 2 * sum(num + 1) + 2;
    }
}
搜索文件

D:盘中,搜索QQScLauncher.exe这个文件,找到后直接输出位置并打开

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

public class Main {
    public static void main(String[] args) throws IOException {
        String path = getPath(new File("D:\\QQ\\Bin"), "QQScLauncher.exe");
        System.out.println(path); // C:\Users\huihui\Desktop\Test\test.txt
    }

    // 在c盘中找到 test.txt 文件,并输出位置
    public static String getPath(File dir, String fileName) throws IOException {
        if(dir == null || !dir.exists() || dir.isFile()) return "您输入的路径有误";
        // 首先遍历一级文件
        File[] files = dir.listFiles();
        // 判断当前目录下是否存在一级文件对象,一级是否可以拿到一级文件对象
        if(files != null && files.length > 0) {
            // 找到里面的文件并对比
            for (File file : files) {
                if(file.isFile() && file.getName().contains(fileName)) {
                    // 打开文件 运行时对象
                    Runtime runtime = Runtime.getRuntime();
                    runtime.exec(file.getAbsolutePath());
                    return file.getAbsolutePath();
                } else {
                    getPath(file, fileName);
                }
            }
        }
        return "没有搜索到";
    }
}
删除非空文件夹
import java.io.File;

public class Main {
    public static void main(String[] args) {
        delFile(new File("C:/Users/huihui/Desktop/kong"));
    }

    // 删除非空文件夹
    public static void delFile(File file) {
        // 判空,不存在或者传的为空则不处理
        if(!file.exists() || file == null) return;
        // 如果是文件,则直接删除
        if(file.isFile()) {
            file.delete();
            return;
        }
        // 存在且是文件夹
        File[] files = file.listFiles(); // 拿到下面的一级文件对象
        if(files == null) return; // 如果文件夹为空(没有权限),则不处理
        // 有权限,不为空的文件夹,遍历进行删除里面的内容,并且最后要把自己空的文件夹删除
        for (File f : files) {
            if(f.isFile()) { // 是文件,直接删除
                f.delete();
            } else { // 文件夹,接着递归
                delFile(f);
            }
        }
        file.delete(); // 最后别忘了把自己空的文件夹删除
    }
}

字符集

在这里插入图片描述

UTF-8

重点:

  • ASCII字符集:只有英文,数字,符号等。占1个字节
  • GBK字符集:汉字占2个字节,英文,数字占1个字节
  • UTF-8字符集:汉字占3个字节,英文,数字占1个字节

字符编码时使用的字符集,喝解码时使用的字符集必须一致,否则就会出现乱码。

但是数字和英文一般都不会出现乱码,因为大部分字符集都要兼容ASCII

编码与解码

编码:把字符按照指定字符集编码成字节

解码:把字节按照指定字符集解码成字符

编码
方法名说明
byte[] getBayes()使用平台的默认字符集将改String编码为一系列字节,将结果存储到新的字节数组中
byte[] getBytes(String charsetName)使用指定的字符集将改String编码为一系列字节,将结果存储到新的字节数组中
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String str = "a的1";
        // 编码
        byte[] b1 = str.getBytes(); // 按照平台默认的字符编码规则编码
        System.out.println(Arrays.toString(b1)); // [97, -25, -102, -124, 49] 97:a 49:1 中间3个表示中文
        byte[] gbks = str.getBytes("GBK");
        System.out.println(Arrays.toString(gbks)); // [97, -75, -60, 49] gbk编码规则中中文是2个字节
    }
}
解码
方法名说明
String(byte[] bytes)通过使用平台的默认字符集解码,指定的字节数组,来构造新的String
String(byte[] bytes, String charsetName)通过指定的字符集解码,指定的租界数组,来构造新的String
import java.io.UnsupportedEncodingException;
import java.util.Arrays;

public class Main {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String str = "a的1";
        // 编码
        byte[] b1 = str.getBytes(); // 按照平台默认的字符编码规则编码
        System.out.println(Arrays.toString(b1)); // [97, -25, -102, -124, 49] 97:a 49:1 中间3个表示中文
        byte[] gbks = str.getBytes("GBK");
        System.out.println(Arrays.toString(gbks)); // [97, -75, -60, 49] gbk编码规则中中文是2个字节
        // 解码
        String s = new String(b1);
        System.out.println(s); // a的1
        String gbk = new String(gbks, "GBK");
        System.out.println(gbk); // a的1
    }
}

IO流

在这里插入图片描述

  • File代表文件。而IO流则可以读写数据

在这里插入图片描述

应用:

在这里插入图片描述

分类:
在这里插入图片描述

具体体系

在这里插入图片描述

输入输出都是以内存为基准的。程序在内存中运行,读写速度快,但是断电或者关闭就会清空数据。而硬盘(又叫磁盘)却可以永久存储数据,但是读写速度相对较慢。

输入:磁盘向内存中输入,也可以说内存读磁盘的数据

输出:内存向磁盘输出,也可以说内存向磁盘写入数据

内存和磁盘想要读写数据,就必须建立连接,而这个链接,就是流。类似与一个管道,只不过管道中流的是数据

数据又分为字节和字符,字节可以操作任意文件,而字符专注与操作各种文本文件(例如txt文件.java文件。。。)

输入流
  • 然后按照文件的最小单位,又可以分为 字节输入流字符输入流
字节输入流
  • InputStream抽象类表示,比较常用的实现类是FileInputStream

作用:

  • 以内存为基准,可以把磁盘文件中的数据以字节的ing是读入到内存中去(也就是读入带程序中去,因为程序放在内存中运行)

首先要创建管道,链接磁盘和内存

构造器说明
public FileInputStream(File file)创建字节输入流管道与源文件接通
public FileInputStream(String pathName)创建字节输入流管道与源文件接通

然后就可以Java提供的方法进行读写了

方法名说明
public int read()每次读取一个字节返回,如果发现没有数据可读会返回-1
public int read(byte[] buffer)每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果返现没有数据可读就会返回-1

测试文件

a测试文件
读取一个字节
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建管道链接
        InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 读数据,一次只读一个字节
        int read = fis.read();
        System.out.println((char) read); // a
        // 最后别忘关闭通道(关闭流)
        fis.close();
    }
}

对上面的改造优化

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

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建管道链接
        InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 读数据,一次只读一个字节
        int num; // 记录读取的字符
        while ((num = fis.read()) != -1) { // 不等于-1说明还有字节
            System.out.print((char) num); // a测试文件
        }
        // 最后别忘关闭通道(关闭流)
        fis.close();
    }
}

但是这种有问题:读取汉字的时候会乱码(因为utf8中,汉字是3个字节,这一次只能读一个,肯定会乱码),并且读取性能不高

读取多个字节
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建管道链接
        InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 读数据,可以自己设定一次读多少个字节
        byte[] bytes = new byte[3];

        // 第一次读取
        // read(byte[] buffer) 返回的是一次读取了多少个字节个数。如果最后一次读取,不到3个字节,那有几个字节,它就是几
        int len = fis.read(bytes);
        System.out.println(len); // 3
        // bytes 中存放的就是读取的3个字节 ['a','1','2']
        System.out.println(new String(bytes)); // a12

        // 第二次读取
        int len2 = fis.read(bytes);
        System.out.println(len2); // 2 因为最后的字节只有2个,不到3个,所以为2
        // bytes 中存放的就是读取的最新的3个字节 ['3','4','2'] 最后一个因为没有,所以还是用的原先的
        System.out.println(new String(bytes)); // 342
        // 但是显然上面的是不对的,正确的应该是 34 不应该有2
        System.out.println(new String(bytes, 0, len2)); // 34 第2个参数是开始位置,第3个参数是结束位置
    }
}

进行循环优化

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

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建管道链接
        InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 读数据,可以自己设定一次读多少个字节
        byte[] bytes = new byte[3];

        // 当读取的长度不为我们设定的3时,就说明读取到到最后一个了
        int len; // 每次读取的字节长度
        while (((len = fis.read(bytes)) != -1)) {
            String s = new String(bytes, 0, len);
            System.out.println(s); // a12 34
        }
        // 关闭管道
        fis.close();
    }
}

但是这种一次读取多个字节,汉字依然是无法读取的。但是文件肯定是要有读取中文的现象,那我们改如何解决中文乱码的问题呢?

其实有一种办法,就是定义一个与文件一样大的字节数组,一次性读取文件的全部字节,这样不会出现中文乱码了

解决中文乱码的方法1

读取的文件:

a中文
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建管道链接
        InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 获取文件大小
        File file = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        long length = file.length(); // 硬盘中的存储空间比较大,所以用的long类型
        // 读数据,可以自己设定一次读多少个字节
        byte[] bytes = new byte[(int)length]; // 内存里的存储空间比较小,所以用的int类型

        fis.read(bytes);
        System.out.println(new String(bytes)); // a中文
        fis.close();
    }
}

但是上面的方法,其实只能读取小的文件,超过int范围的文件一次性就读取不了了

解决中文乱码的方法2

Java官方为InputStrem提供了方法,可以直接把文件的全部字节读取到一个字节数组中返回

public byte[] readAllbytes() throw IOException // 直接将当前字节输入流对应的文件对象的字节数据撞到一个字节数组返回

那上面方法1就可以进行下面的简化

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

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建管道链接
        InputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 获取全部字节文件,并返回到一个新的字节数组
        byte[] bytes = fis.readAllBytes();

        String s = new String(bytes);
        System.out.println(s); // a中文
        fis.close();
    }
}
字符输入流
  • Reader抽象类表示,比较常用的实现类是FileReader

作用:

  • 以内存为基准,可以把文件中的数据以字符的形式读入到内存中去

首先要创建管道,链接磁盘和内存

构造器说明
public FileReader(File file)创建字符输入流管道与文件接通
public FileReader(String pathName)创建字符输入流管道与源文件接通

然后就是方法进行写入

方法名说明
public int read()每次读取一个字符返回,如果发现没有数据可读会返回-1
public int read(char[] buffer)每次用一个字符数组去读取数据,返回字符数组读取了多少个字符,如果发现没有数据可读会返回-1
读取一个字符
import java.io.FileReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建一个字符链接管道
        FileReader fr = new FileReader("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 然后开始读,一次读取一个字符
        int read = fr.read();
        System.out.println((char) fr.read());
        fr.close();
    }
}

上面的可以进行优化

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

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建一个字符链接管道
        FileReader fr = new FileReader("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 然后开始读,一次读取一个字符
        int num;
        while ((num = fr.read()) != -1) {
            System.out.println((char) num);
        }
        fr.close();
    }
}
读取多个字符
import java.io.FileReader;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建一个字符链接管道
        FileReader fr = new FileReader("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        char[] chars = new char[3];
        // 读取多个字符
        int len; // 记住每次读取了多少个字符
        while ((len = fr.read(chars)) != -1) {
            System.out.print(new String(chars,0,len)); // 被复制的内容
        }
        fr.close();
    }
}
输出流
  • 然后按照文件的最小单位,又可以分为 字节输出流字符输出流
字节输出流
  • OutputStream抽象类表示,比较常用的实现类是FileOutputStream

作用:

  • 以内存为基准,把内存中的数据以字节的形式写出到文件中去

首先要创建管道,链接磁盘和内存

构造器说明
public FileOutputStream(File file)创建字节输出流管道与源文件接通
public FileOutputStream(String filePath)创建字节输出流管道与源文件接通
public FileOutputStream(File file,boolean append)创建字节输出流管道与源文件对象接通,可追加数据
public FileOutputStream(String filePath,boolean append)创建字节输出流管道与源文件对象接通,可追加数据

然后就可以Java提供的方法进行读写了

方法名说明
public void write(int a)写一个字节出去
public void write(byte[] buffer)写一个字节数组进去
public void write(byte[] buffer, int pos, int len)写一个字节数组的一部分进去
public void close() throw IOException关闭流

测试文件(空文件)

写入磁盘一个字节
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建一个内存到硬盘的管道
        OutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 往磁盘中写入一个字节
        fos.write(97); // 97 ASCII 表示a
        fos.write('b'); // ''  单引号包裹的本来就是一个字节 byte类型
        fos.close();
    }
}

也是不能直接写入中文,因为在utf-8编码中,一个中文是占3个字节,这里是只写入一个字节。所以写入中文会乱码,但是我们可以通过写入一个字节数组,来进行添加中文,通过调用StringgetBytes()方法可以得到对应的字节数组

添加中文
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建一个内存到硬盘的管道
        OutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 往磁盘中写入一个字节
        fos.write(97); // 97 ASCII 表示a
        fos.write('b'); // ''  单引号包裹的本来就是一个字节 byte类型
        // 添加中文 通过 String 的 getBytes() 方法可以直接得到一个字节数组
        byte[] bytes = "中文".getBytes();
        fos.write(bytes);
        fos.close();
    }
}
指定添加部分
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建一个内存到硬盘的管道
        OutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 往磁盘中写入一个字节
        fos.write(97); // 97 ASCII 表示a
        fos.write('b'); // ''  单引号包裹的本来就是一个字节 byte类型
        // 添加中文 通过 String 的 getBytes() 方法可以直接得到一个字节数组
        byte[] bytes = "中文".getBytes();
        fos.write(bytes);
        // 当然,也可以指定添加的部分
        byte[] bytes2 = "添加前两个字".getBytes();
        fos.write(bytes2,0,6); // 一个中文是3个字节,所以添加前两个字,只需要添加6个字节
        fos.close();
    }
}

但是上面的添加,都会直接把原先文件里的东西全替代掉。有的时候,我们其实是不想让添加的内容把原先的内容替换掉的,所以就需要创建管道的时候指定是添加的(构造器的第二个参数为true)

后面追加内容

测试文件

文件原本的内容
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class Main {
    public static void main(String[] args) throws IOException {
        // 首先创建一个内存到硬盘的管道,如果是追加内容,则需要把第二个参数设为true
        OutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt",true);
        // 往磁盘中写入一个字节
        fos.write(97); // 97 ASCII 表示a
        fos.write('b'); // ''  单引号包裹的本来就是一个字节 byte类型
        // 添加中文 通过 String 的 getBytes() 方法可以直接得到一个字节数组
        byte[] bytes = "中文".getBytes();
        fos.write(bytes);
        // 当然,也可以指定添加的部分
        byte[] bytes2 = "添加前两个字".getBytes();
        fos.write(bytes2,0,6); // 一个中文是3个字节,所以添加前两个字,只需要添加6个字节
        // 添加换行
        fos.write("\r\n".getBytes());
        fos.close();
    }
}

最后文件显示

文件原本的内容
ab中文添加
文件复制
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class Main {
    public static void main(String[] args) throws IOException {
        // 1. 首先创建一个输入流,把需要复制的内容用一个字节数组存储起来
        FileInputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 1.1 创建一个存储字节的数组
        byte[] bytes = fis.readAllBytes();
        
        // 2. 把存起来的字符数组输出到指定的文件里去
        FileOutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\get.txt", true);
        fos.write(bytes);

        fis.close();
        fos.close();
        System.out.println("复制完成");
    }
}

但是上面这种,文件特别大的话,可能会出错。下面有一个更通用的方法

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

public class Main {
    public static void main(String[] args) throws IOException {
        // 1. 首先创建一个输入流,把需要复制的内容用一个字节数组存储起来
        FileInputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        // 2. 把存起来的字符数组输出到指定的文件里去  这里后面不加true也是追加,因为同一个流不会覆盖
        FileOutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\get.txt", true);

        // 3. 创建一个字节数组,负责转移字节数据
        byte[] bytes = new byte[1024]; // 先给个1kb
        // 4. 然后开始循环写入
        int len; // 记录每次读取了多少个字节
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes,0,len);
        }

        fis.close();
        fos.close();
        System.out.println("复制完成");
    }
}
字符输出流
  • Writer抽象类表示,比较常用的实现类是FileWriter
  • 字符输出流输出字符后,必须输出流,或者关闭流,写出去的数据才能生效

作用:

  • 以内存为基准,可以把内存中的数据以字符的形式输出到磁盘中去

首先要创建管道,链接磁盘和内存

构造器说明
public FileWriter(File file)创建字符输出流管道与源文件对象接通
public FileWriter(String pathName)创建字符输出流管道与源文件路径接通
public FileWriter(File file,Boolean append)创建字节输出流管道与源文件对象接通,可追加数据
public FileWriter(String fillpath,boolean append)创建字节输出流管道与源文件路径接通,可追加数据

然后就是方法进行输出

方法名说明
void write(int c)每次写入一个字符,如果发现没有数据可写会返回-1
void write(String str)写一个字符串
void write(String str, int off, int len)写一个字符串的一部分
void write(char[] cbuf)写入一个字符数组
void write(char[] cbuf, int off, int len)写入字符数组的一部分
写入磁盘一个字符
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                // 创建链接管道
                Writer fw = new FileWriter(f);
                ) {
            // 一次写入磁盘一个字符
            fw.write(97);
            fw.write('b');
            fw.write('中');
            // 或者写一个字符串
            fw.write("国");
            // 或者写入字符串的一部分
            fw.write("人123",0,1);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
写入多个字符
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                // 创建链接管道
                Writer fw = new FileWriter(f);
                ) {
            // 写入一个字符数组
            char[] chars = "1a中".toCharArray();
            fw.write(chars);
            // 直接写入一个字符串
            fw.write("几点开始");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
关闭流
  • 调用流的close方法即可关闭流的通道。但是有的时候,可能代码会出现一些问题,造成没法办法正常走到close方法,所以就需要错误捕获
tryCatch

try { // 可能会出现错误的代码 } catch (异常类名 变量名) { // 错误处理 } finally { // 不管成功还是失败都一定会执行的 }

  • 除非JVM终止(System.exit()),不然finally里的代码一定会执行的
  • 作用:一般用在程序执行完成后进行资源的释放操作
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Objects;

public class Main {
    public static void main(String[] args) {
        // 快捷键:选中代码 ctrl + alt + t
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            // 1. 首先创建一个输入流,把需要复制的内容用一个字节数组存储起来
            fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
            // 2. 把存起来的字符数组输出到指定的文件里去  这里后面不加true也是追加,因为同一个流不会覆盖
            fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\get.txt", true);

            // 3. 创建一个字节数组,负责转移字节数据
            byte[] bytes = new byte[1024]; // 先给个1kb
            // 4. 然后开始循环写入
            int len; // 记录每次读取了多少个字节
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes,0,len);
            }

            System.out.println("复制完成");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if(Objects.isNull(fis)) fis.close();
                if(Objects.isNull(fos)) fos.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
tryWithResource
  • tryCatch更简单
  • 括号里面只能放资源对象,例如流对象,并且会自动关闭流
  • 资源都会实现一个AutoCloseable接口,并且资源都会有一个close方法,并且会自动调用

try(定义资源1; 定义资源2; …) { // 可能出现异常的代码; } carch(异常类名 变量名) { // 异常的处理代码; }

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

public class Main {
    public static void main(String[] args) {
        try(
                // 1. 首先创建一个输入流,把需要复制的内容用一个字节数组存储起来
                FileInputStream fis = new FileInputStream("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
                // 2. 把存起来的字符数组输出到指定的文件里去  这里后面不加true也是追加,因为同一个流不会覆盖
                FileOutputStream fos = new FileOutputStream("D:\\Idea\\Codeing\\Day01\\src\\get.txt", true);
                ) {
            // 3. 创建一个字节数组,负责转移字节数据
            byte[] bytes = new byte[1024]; // 先给个1kb
            // 4. 然后开始循环写入
            int len; // 记录每次读取了多少个字节
            while ((len = fis.read(bytes)) != -1) {
                fos.write(bytes,0,len);
            }

            System.out.println("复制完成");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

缓冲流

  • 对原始流进行包装,以提高原始流读写数据的性能
字节缓冲输入流

测试数据

abcd

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\IDEA\\code\\hello\\src\\test.txt");
        try(
                FileInputStream fis = new FileInputStream(f);
                InputStream bis = new BufferedInputStream(fis);
                ) {
            byte[] bytes = new byte[3];

            int len;
            while ((len = bis.read(bytes)) != -1) { // 不为-1说明就有值
                System.out.print(new String(bytes, 0, len)); // abcd
            }
        } catch (Exception e){
            e.printStackTrace(); //打印错误信息
        }
    }
}
字节缓冲输出流
import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\IDEA\\code\\hello\\src\\test.txt");
        try(
                // 建立管道链接
                OutputStream os = new FileOutputStream(f,true);
                OutputStream bos = new BufferedOutputStream(os);
                ) {
            // 一次写入磁盘一个字节
            bos.write(97); // 97 ASCII中是a
            bos.write('b');
            // os.write('中'); // 添加中文是不行的,因为在utf8编码中,中文是3个字节,这里只添加一个,肯定不行
            // 一次写入磁盘多个字节
            byte[] bytes = "中国".getBytes();
            bos.write(bytes);
            // 一次写入指定个数的
            byte[] bytes1 = "abc".getBytes();
            bos.write(bytes1, 0, 2);
        } catch (Exception e){
            e.printStackTrace(); //打印错误信息
        }
    }
}
字符缓冲输入流
import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\IDEA\\code\\hello\\src\\test.txt");
        try(
                // 建立管道链接
                Reader fr = new FileReader(f);
                Reader br =  new BufferedReader(fr);
                ) {
            // 1. 一次读取一个字符
            int r1 = br.read();
            System.out.println(r1); // 99 ASCII中表示c
            System.out.println((char) r1); // c
            // 2. 一次读取指定次数的字符
            char[] chars = new char[4];
            int len;
            while ((len = br.read(chars)) != -1) { // 只要不为-1,就说明还有值
                String s = new String(chars, 0, len);
                System.out.print(s); // eshishuju
            }
            // 3. 一次读取多个字符,并且指定位置和个数
            int r2 = br.read(chars, 0, 3);
            System.out.println(r2); // -1 因为上面读完了
        } catch (Exception e){
            e.printStackTrace(); // 打印错误信息
        }
    }
}
字符缓冲输出流
import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\IDEA\\code\\hello\\src\\test.txt");
        try(
                // 建立管道链接
                Writer fw = new FileWriter(f);
                Writer bw =  new BufferedWriter(fw);
                ) {
            // 1. 一次写入磁盘一个字符
            bw.write(97);
            bw.write('b');
            bw.write('中');
            // 2. 一次写入一个字符数组
            char[] charArray = "你好呀".toCharArray();
            bw.write(charArray);
            // 3. 还可以直接写入字符串,这个就很方便呀
            bw.write("Java");
            // 4. 还可以指定起始位置和个数
            bw.write("Web",0,3);
        } catch (Exception e){
            e.printStackTrace(); // 打印错误信息
        }
    }
}

转换流

字符输入转换流
InputStreamReader
  • 解决不同编码时,字符读取文本内容乱码的问题
  • 解决思路:先获取文件的原始字节流,再按其真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了
构造器说明
public inputStreamReader(InputStream is)把原始的字节输入流,按照代码默认编码转成字符输入流(与直接用FileReader的效果一样)
public InputStreamReader(InputStream is,String charset)把原始的字节输入流,按照指定字符集编码转成字符输入流

文件A GBK编码格式

中几点开始
import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                Reader br = new BufferedReader(new FileReader(f));
                ) {
            // � 因为编译器默认编码是utf8,但是文件里面的编码是gbk 所以乱码了
            System.out.println((char) br.read());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

解决办法就是字符输入转换流

import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                InputStream is = new FileInputStream(f);
                // 转成对应编码的字节输入流
                Reader isr = new InputStreamReader(is, "GBK");
                // 这样再操作就不会有乱码问题了
                Reader br = new BufferedReader(isr);
                ) {
            int c;
            while ((c = br.read()) != -1) {
                System.out.print((char) c);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
字符输出转换流
OutputStreamWrite
  • 可以控制写出去的字符使用什么字符集编码
  • 解决思路:获取字节输出流,再按照指定的字符集编码将其转换为字符输出流,以后写出去的字符就会用该字符集编码了
构造器说明
public OutputStreamWriter(OutStream os)可以把原始的字节输出流,按照代码默认编码转换成字符输出流
public OutputStreamWriter(OutputStream os,String charset)可以把原始的字节输出流,按照指定字符集编码转成字符输出流

文件A GBK编码格式

import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                Writer bw = new BufferedWriter(new FileWriter(f));
                ) {
            bw.write("你好呀"); // 啊浣犲ソ鍛�     乱码了,因为写入的是utf8编码的字符
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

解决办法就是字符输出转换流

import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                OutputStream fos = new FileOutputStream(f, true);
                // 把原始的字节输入流转成固定格式的输出流
                Writer psw = new OutputStreamWriter(fos, "GBK");
                Writer bw = new BufferedWriter(psw);
                ) {
            bw.write("你好呀"); // 啊你好呀
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
控制写的字符使用的字符集

有两种实现方法:

  1. 调用String提供的getBytes方法

String d = “你好呀”; byte[] bytes = d.getBytes(“GBK”);

  1. 使用字符输出转换流实现

打印流

  • 打印流可以实现更方便,更高效的打印数据出去,能实现打印啥出去就是啥
printStream
  • 属于字节输出流
构造器说明
public PrintStream(OutputStream/File/String)打印流直接通向字节输出流/文件/文件路径
public PrintStream(String fileName,Charset charset)可以指定写出去的字符编码
public PrintStream(OutputStream out, boolean autoFlush)可以指定实现自动刷新
public PrintStream(OutputStream out, bollean autoFlush, String encoding)可以指定实现自动刷新,并可指定字符的编码

写数据的方法

方法名说明
public void println(Xxx xx)打印任意类型的数据出去,自带换行
public void write(int/byte[]/byte[]的一部分)可以支持写字节数据进去

基本使用

import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                PrintStream ps = new PrintStream(f);
                ) {
            ps.println(97);
            ps.println('b');
            ps.println("你好呀"); // 97 \n b \n 你好呀
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

指定字符集

import java.io.*;
import java.nio.charset.Charset;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                // 指定写入的编码格式
                PrintStream ps = new PrintStream(f, Charset.forName("GBK"));
                ) {
            ps.println(97);
            ps.println('b');
            ps.println("你好呀"); // 97 \n b \n 你好呀
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
PrintWriter
  • 属于字符输出流
构造器说明
public PrintWriter(OutputStream/Writer/File/String)打印流直接通向字节输出流/字符输出流/文件/文件路径
public PrintWriter(String fileName,Charset charset)可以指定写出去的字符编码
public PrintWriter(OutputStream out/Writer, boolean autoFlush)可以指定实现自动刷新
public PrintWriter(OutputStream out, bollean autoFlush, String encoding)可以指定实现自动刷新,并可指定字符的编码

写数据的方法

方法名说明
public void println(Xxx xx)打印任意类型的数据出去,自带换行
public void write(int/String/char[])可以支持写字符数据出去

基本使用

import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                PrintWriter pw = new PrintWriter(f);
        ) {
            pw.println(97);
            pw.println('a');
            pw.println("你好呀"); // 97 \n b \n 你好呀
        } catch (IOException e) {
            throw new RuntimeException(e); 
        }
    }
}

指定字符集

import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                PrintWriter pw = new PrintWriter(f,"GBK");
        ) {
            pw.println(97);
            pw.println('a');
            pw.println("你好呀");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
追加数据
  • 因为PrintStreamPrintWriter是高级流,所以不能直接追加数据,但是我们在调用构造器的时候,可以传入一个低级输出流,在低级输出流中可以指定追加
import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                PrintWriter pw = new PrintWriter(new FileOutputStream(f, true));
        ) {
            pw.println(97);
            pw.println('a');
            pw.println("你好呀");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
区别
  • 打印数据的功能上一摸一样:都是使用方便,性能高效
  • PrintStream继承字节输出流OutputStream,因此支持字节数据的方法
  • PrintWriter继承字符输出流Writer,因此支持字符数据的方法
应用

输出语句的重定向,可以把输出语句的打印位置改到某个文件中去

import java.io.*;

public class Main {
    public static void main(String[] args) {
        System.out.println("会打印文件外");
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                // PrintWriter pw = new PrintWriter(new FileOutputStream(f));
                PrintStream ps = new PrintStream(f);
        ) {
            // 把系统默认的打印流对象改成自己设置的打印流
            System.setOut(ps);

            System.out.println("会打印在文件里");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

数据流

  • 操作的都是字节的
DataOutputStream
  • 属于字节输出流,允许把数据和其类型一并写出去
构造器说明
public DataOutputStream(OutputStream out)创建新数据输出流包装基本的字节输出流

方法

方法说明
public final void writeByte(int v) throws IOException将byte类型的数据写入基本的字节输出流
public final void writeInt(int v) throws IOException将Int类型的数据写入基本的字节输出流
public final void writeDouble(Double v) throws IOException将Double类型的数据写入基本的字节输出流
public final void writeUtf(String str) throws IOException将字符串数据以UTF-8编码字节写入基本的字节输出流
public void write(int/byte[]/byte[]的一部分)支持写字节数据出去

案例

import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                OutputStream fps = new FileOutputStream(f);
                // 写入数据和其类型,就需要用到数据流
                DataOutputStream dos = new DataOutputStream(fps);
        ) {
            // 写入一个字节
            dos.writeByte(97); // a
            // 写入一个数字
            dos.writeInt(97); // 97
            // 写入一个布尔
            dos.writeBoolean(true);
            // 写入一个小数
            dos.writeDouble(99.99);
            // 写入一个字符串
            dos.writeUTF("你好呀"); // a   a@X�\(� 	你好呀    这不是乱码,是有类型就这样
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
DataInputStream
  • 属于字节输入流,用于读取数据输出流写出去的数据
构造器说明
public DataInputStream(InputStream is)创建新数据输入流包装基本的字节输出流

方法

方法说明
public final void readByte() throws IOException读取字节数据返回
public final int readInt() throws IOException读取int类型的数据返回
public final double readDouble() throws IOException读取double类型的数据返回
public final String readUtf() throws IOException读取字符串数据返回(UTF-8)
public int readInt() / public int read(byte[])支持读字节数据进来

案例:读的顺序要跟写的顺序一样

import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
             InputStream fis = new FileInputStream(f);
             // 我们需要读取带有值和类型的,所以就需要用到数据输入流
             DataInputStream dis = new DataInputStream(fis);
        ) {
            // System.out.println(dis.read()); // 97
            System.out.println(dis.readByte()); // 97
            System.out.println(dis.readInt()); // 97
            System.out.println(dis.readBoolean()); // true
            System.out.println(dis.readDouble()); // 99.99
            System.out.println(dis.readUTF()); // 你好呀
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

序列化流

  • 我们想把Java对象存进文件去,就需要用到对象序列化流
  • 则反序列化就是把存进去的对象序列化读取出来
  • 属于字节流
ObjectOutputStream
  • 可以把Java对象进行序列化:把Java对象存入到文件中去
  • transient修饰的成员可以不参与对象序列化
构造器说明
public ObjectOutputStream(OutputStream out)创建对象字节输出流,包装基础的字节输出流

方法

方法名说明
public final void writeObject(Object o) throws IOException把对象写出去

案例

Student.java

package Demo;
import java.io.Serializable;

// 注意:对象如果需要序列化,必须实现序列化接口
public class Student implements Serializable {
    private String name;
    private int age;
    // private double score;
    // transient 修饰,则这个成员变量将不参与序列化(因为有的时候,其实不想要某个属性展示的,例如密码)
    private transient double score;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public Student() {
    }

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

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

Main.java

import Demo.Student;
import java.io.*;

public class Main {
    public static void main(String[] args) {
        Student zs = new Student("张三", 25, 100.00);

        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
             OutputStream fos = new FileOutputStream(f);
             // 我们要写入对象,就需要用到对象序列化流
             ObjectOutputStream ois = new ObjectOutputStream(fos);
        ) {
            ois.writeObject(zs);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
ObjectInputStream
  • 可以把Java对象进行反序列化:把存储在文件中的Java对象读入到内存中来
构造器说明
public ObjectInputStream(InputStream is)创建对象字节输入流,包装基础的字节输入流

方法

方法名说明
public final Object readObject()把存储在文件中的Java对象读出来

案例

import Demo.Student;
import java.io.*;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                InputStream fis = new FileInputStream(f);
                // 我们想要读取存储在文件中的对象,就需要对象反序列化
                ObjectInputStream ois = new ObjectInputStream(fis);
        ) {
            Student s1 = (Student) ois.readObject();
            System.out.println(s1);//Student{name='张三', age=25, score=0.0} 这里score并不参与序列化,所以为初始值
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
实现一次多个对象序列化
  • 用一个ArrayList集合存储多个对象,然后直接对集合进行序列化即可
  • ArrayList集合已经实现了序列化接口

Student.java

package Demo;
import java.io.Serializable;

// 注意:对象如果需要序列化,必须实现序列化接口
public class Student implements Serializable {
    private String name;
    private int age;
    // private double score;
    // transient 修饰,则这个成员变量将不参与序列化(因为有的时候,其实不想要某个属性展示的,例如密码)
    private transient double score;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getScore() {
        return score;
    }

    public void setScore(double score) {
        this.score = score;
    }

    public Student() {
    }

    public Student(String name, int age, double score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

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

写入到磁盘

import Demo.Student;
import java.io.*;
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        Student zs = new Student("张三", 25, 100.00);
        Student ls = new Student("李四", 26, 100.00);
        ArrayList<Student> students = new ArrayList<>();
        students.add(zs);
        students.add(ls);

        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                OutputStream fos = new FileOutputStream(f);
                // 我们要写入对象,就需要用到对象序列化流
                ObjectOutputStream ois = new ObjectOutputStream(fos);
        ) {
            // 把整个ArrayList集合对象写进去,方便我们遍历集合去读
            ois.writeObject(students);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

读取磁盘

import Demo.Student;
import java.io.*;
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        File f = new File("D:\\Idea\\Codeing\\Day01\\src\\test.txt");
        try(
                InputStream fis = new FileInputStream(f);
                // 我们想要读取存储在文件中的对象,就需要对象反序列化
                ObjectInputStream ois = new ObjectInputStream(fis);
        ) {
            ArrayList<Student> students = (ArrayList<Student>) ois.readObject();
            System.out.println(students); // [Student{name='张三', age=25, score=0.0}, Student{name='李四', age=26, score=0.0}]
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

IO框架

  • 框架就是解决某类问题,编写的一套类,接口等,可以理解成一个半成品,大多数框架都是第三方研发的

形式:

一般都是把类,接口等编译成class形式,再压缩成一个.jar结尾的文件发行出去

IO框架封装了Java提供的对文件,数据进行操作的代码,对外提供了更简单的方式来对文件进行操作,对数据进行读写等

Commons-io
  • apache开源基金组织提供的一组有关IO操作的小框架,目的是提高IO流的开发效率

FileUtils类

FileUtils类提供的部分方法展示说明
public static void copyFile(File srcFile,File destFile)复制文件
public static void copyDirectory(File srcDir,File destDir)复制文件夹
public static void deleteDirectory(File directory)删除文件夹
public static String readFileToString(File file,String encoding)读数据
public static void writeStringToFile(File file,String data,String charname,boolean append)写数据
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.nio.charset.Charset;

public class Main {
    public static void main(String[] args) {
        // FileUtils
        try {
            // 拷贝文件
            FileUtils.copyFile(new File("D:\\Idea\\Codeing\\Day01\\src\\in.txt"),new File("D:\\Idea\\Codeing\\Day01\\src\\out.txt"));
            // 拷贝文件夹
            FileUtils.copyDirectory(new File("C:\\Users\\huihui\\Desktop\\in"),new File("C:\\Users\\huihui\\Desktop\\out"));
            // 删除文件夹(非空的也可以)
            FileUtils.deleteDirectory(new File("C:\\Users\\huihui\\Desktop\\out"));
            // 读数据
            String s = FileUtils.readFileToString(new File("D:\\Idea\\Codeing\\Day01\\src\\in.txt"));
            System.out.println(s); // 111 不推荐使用这个了
            // 写数据 不推荐使用这个了
            FileUtils.writeStringToFile(new File("D:\\Idea\\Codeing\\Day01\\src\\in.txt"), "添加进去");
            // 追加数据
            FileUtils.writeStringToFile(new File("D:\\Idea\\Codeing\\Day01\\src\\in.txt"),"追加的数据", Charset.forName("UTF-8"),true);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

IOUtils类

IOUtils类提供的部分方法展示说明
public static int copy(InputStream inputStream,outputStream outputStream)复制文件
public static int copy(Reader reader,Writer writer)复制文件
public static void write(String data,OutputStream output,String charsetName)写数据

其实Java原生也提供了一些一行代码操作文件的处理(但是都没有成功,不知道为什么)

import java.nio.file.Files;
import java.nio.file.Path;

public class Main {
    public static void main(String[] args) {
        try {
            // 拷贝文件
            // Files.copy(Path.of("Day01\\src\\in.txt"),Path.of("Day01\\src\\out.txt"));
            // 读文件
            // System.out.println(Files.readString(Path.of("Day01\\\\src\\\\in.txt"))); //
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

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

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

相关文章

光学知识整理-偏振光

偏振光 目录基础概念基础概念的补充平面偏振光&#xff08;线偏振光&#xff09;部分偏振光圆偏振光椭圆偏振光菲涅耳公式相位关系 反射折射所引起的偏振态的改变斯托克斯倒逆关系重要参数 目录 基础概念 光是横波&#xff1a;光是电磁波,其电场分量(电场强度)E、磁场分量(磁…

网易面试:什么是SPI,SPI和API有什么区别?

说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 什么是SPI&#xff0c;SPI和API有什么区别&#xff1f; 最近有小…

推理引擎之模型压缩浅析

目录 前言1. 模型压缩架构和流程介绍2. 低比特量化原理2.1 量化基础介绍2.2 量化方法2.3 量化算法原理2.4 讨论 3. 感知量化训练QAT原理3.1 QAT原理3.2 量化算子插入3.3 QAT训练流程3.4 QAT衍生研究3.5 讨论 4. 训练后量化PTQ4.1 动态PTQ4.2 静态PTQ4.3 KL散度实现静态PTQ4.4 量…

PyTorch入门教学——Transforms使用

1、Transforms简介 Transforms在是计算机视觉工具包torchvision下的包&#xff0c;常用于对图像进行预处理&#xff0c;提高泛化能力。具体有&#xff1a; 数据中心化、数据标准化、缩放、裁剪、旋转、翻转、填充、噪声添加、灰度变换、线性变换、仿射变换和亮度、饱和度及对比…

springboot 程序设计优雅退出

一 springboot优雅退出 1.1 概述 在springboot2.3版本后&#xff0c;实现了优雅退出功能。当server.shutdowngraceful启用时&#xff0c;在 web 容器关闭时&#xff0c;web 服务器将不再接收新请求&#xff0c;并将剩余活动执行完成给设置一个缓冲期。缓冲期 timeout-per-shu…

Mysql数据库 2.SQL语言 数据类型与字段约束

Mysql数据类型 数据类型&#xff1a;指的是数据表中的列文件支持存放的数据类型 1.数值类型 Mysql当中有多种数据类型可以存放数值&#xff0c;不同的类型存放的数值的范围或者形式是不同的 注&#xff1a;前三种数字类型我们在实际研发中用的很少&#xff0c;一般整数类型…

2525.根据规则将箱子分类/并查集/动态规划

2525. 根据规则将箱子分类 - 力扣&#xff08;LeetCode&#xff09; 给你四个整数 length &#xff0c;width &#xff0c;height 和 mass &#xff0c;分别表示一个箱子的三个维度和质量&#xff0c;请你返回一个表示箱子 类别 的字符串。 如果满足以下条件&#xff0c;那么…

AndroidStudio如何设置中文

AndroidStudio如何设置中文 文章目录 AndroidStudio如何设置中文一、前言二、如何安装中文插件参考资料&#x1f498; 一、前言 Android Studio 是一个为 Android 平台开发程序的集成开发环境&#xff08;IDE&#xff09;。2013年5月16日在 Google I/O 上发布&#xff0c;可供…

springboot+vue开发的视频弹幕网站动漫网站

springbootvue开发的视频弹幕网站动漫网站 演示视频 https://www.bilibili.com/video/BV1MC4y137Qk/?share_sourcecopy_web&vd_source11344bb73ef9b33550b8202d07ae139b 功能&#xff1a; 前台&#xff1a; 首页&#xff08;猜你喜欢视频推荐&#xff09;、轮播图、分类…

四、网络请求与路由

一、网络请求 1、Axios请求 Axios是一个基于promise的网络请求库 &#xff08;1&#xff09;安装 npm install --save axios&#xff08;2&#xff09;引入 import axios from "axios"全局引入 import axios from "axios" import { createApp } from …

深度学习_3_实战_房价预测

梯度 实战 代码&#xff1a; # %matplotlib inline import random import torch import matplotlib.pyplot as plt # from d21 import torch as d21def synthetic_data(w, b, num_examples):"""生成 Y XW b 噪声。"""X torch.normal(0,…

面试知识储备--打包工具篇(webpack和vite)

1.vite常用配置 常用配置 1.preprocessorOptions 传递给 CSS 预处理器的配置选项 2.PostCSS 也是用来处理 CSS 的&#xff0c;只不过它更像是一个工具箱&#xff0c;可以添加各种插件来处理 CSS 3.resolve.extensions 导入时想要省略的扩展名列表。默认值为 [‘.mjs’, ‘.js’…

小团队之间有哪些好用免费的多人协同办公软件

在小团队协作中&#xff0c;选择适合的多人协同办公软件是提高工作效率和团队协作的重要一环。幸运的是&#xff0c;市场上有许多大多数功能都免费的多人协同办公软件&#xff0c;为小团队提供了强大的协作功能和便捷的工作环境。 在本文中&#xff0c;我将根据自己多年的在线…

2.2.C++项目:网络版五子棋对战之数据管理模块的设计

文章目录 一、数据管理模块实现&#xff08;一&#xff09;功能 二、设计&#xff08;一&#xff09;数据库设计&#xff08;二&#xff09;创建user_table类 一、数据管理模块实现 &#xff08;一&#xff09;功能 数据管理模块主要负责对于数据库中数据进行统一的增删改查管…

3ds Max2023安装教程(最新最详细)

目录 一.简介 二.安装步骤 软件&#xff1a;3ds Max版本&#xff1a;2023语言&#xff1a;简体中文大小&#xff1a;6.85G安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU3GHz 内存16G(或更高&#xff09;下载通道①百度网盘丨64位下载链接&#xff1a; …

【蓝桥每日一题]-动态规划 (保姆级教程 篇10)#方格取数

高能预警&#xff1a;讲了这么久动态规划了&#xff0c;该上点有难度的题吧 目录 题目&#xff1a;方格取数 思路&#xff08;解法一&#xff09;&#xff1a; 解法二&#xff1a; 题目&#xff1a;方格取数 思路&#xff08;解法一&#xff09;&#xff1a; 如果只有两个方向…

openCV Cuda

下载 git clone https://github.com/opencv/opencv.git git clone https://github.com/opencv/opencv_contrib.git确保准备好以下内容 1&#xff1a; visual studio &#xff08;不是vs code&#xff09; 2&#xff1a;下载后的两个包裹会放在以下结构 这样放的原因是我Ub…

Java EE-使用Servlet搭建一个简单的前后端交互程序

上述前端和后端的代码如下&#xff1a; 前端&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"vie…

数据库笔记——SQL语言DQL语句

schema等于database 数据库 datagrip中使用控制台进行操作&#xff1a; 右键new QueryConsole 创建表格create table中&#xff1a; 1. 括号内不管是定义属性还是声明约束&#xff0c;都使用逗号分隔&#xff0c;最后一句不用逗号 2. 括号外使用分号 DDL&#xff1a;数据库定…

python接口自动化测试(单元测试方法)

一、环境搭建 python unittest requests实现http请求的接口自动化Python的优势&#xff1a;语法简洁优美, 功能强大, 标准库跟第三方库灰常强大&#xff0c;建议大家事先了解一下Python的基础;unittest是python的标准测试库&#xff0c;相比于其他测试框架是python目前使用最广…