JavaSE(IO流)

File类

文件和目录的抽象表示

静态方法

static String pathSeparator:与系统有关的路径分隔符
static String separator:与系统有关的默认名称分隔符

window:\
linux:/

package alive.a_flie;

import java.io.File;

/**
 * @Author zyj
 * @Date 2024/09/19 10:16
 * @Description
 */
public class Test {
    public static void main(String[] args) {
        System.out.println("File.pathSeparator = " + File.pathSeparator);
        System.out.println("File.separator = " + File.separator);
        //File.pathSeparator = ;
        //File.separator = \
        String path1 = "D:\\code\\alive";
        System.out.println("path1 = " + path1);
        String path2 = "D:" + File.separator + "code" + File.separator + "alive";
        System.out.println("path2 = " + path2);
        
    }
}

构造方法

File(String parent,String child):根据所填写的路径创建File对象,parent:父路径,child:子路径
File(File parent,String child):根据所填写的路径创建File对象,parent:父路径,是一个File对象,child:子路径
File(String pathname):根据所填写的路径创建File对象,pathname:直接指定路径

package alive.a_flie;

import java.io.File;

/**
 * @Author zyj
 * @Date 2024/09/19 10:16
 * @Description
 */
public class Test {
    public static void main(String[] args) {
        File f1 = new File("D:\\code\\alive", "test.txt");
        System.out.println("f1 = " + f1);
        File f2 = new File(new File("D:\\code\\alive"), "test.txt");
        System.out.println("f2 = " + f2);
        File f3 = new File("D:\\code\\alive\\test.txt");
        System.out.println("f3 = " + f3);
    }
}

File的获取方法

String getAbsolutePath():获取File的绝对路径(带盘符路径)
String getPath():获取的是封装路径,new File对象时写的路径
String getName:获取的是文件或者文件夹名称
long length():获取的是文件的长度(文件字节数)

package alive.a_flie;

import java.io.File;

/**
 * @Author zyj
 * @Date 2024/09/19 10:16
 * @Description
 */
public class Test {
    public static void main(String[] args) {
        File file = new File("D:\\code\\alive\\test.txt");
        System.out.println("file.getAbsolutePath() = " + file.getAbsolutePath());
        File f1 = new File("test.txt");
        System.out.println("f1.getAbsolutePath() = " + f1.getAbsolutePath());
        System.out.println("file.getPath() = " + file.getPath());
        System.out.println("file.getName() = " + file.getName());
        System.out.println("file.length() = " + file.length());
        //file.getAbsolutePath() = D:\code\alive\test.txt
        //f1.getAbsolutePath() = D:\code\alive\javaSE\test.txt
        //file.getPath() = D:\code\alive\test.txt
        //file.getName() = test.txt
        //file.length() = 0
    }
}

File方法

boolean crateNewFile():创建文件;
① 如果创建的文件已经存在,则创建失败,返回false
② 如果创建的文件之前没有,则创建失败,返回true
boolean mkdirs():创建文件夹,既可以多级文件夹又可以创建单级文件夹
① 如果创建的文件夹已经存在,则创建失败,返回false
② 如果创建的文件夹之前没有,则创建失败,返回true

boolean delete():删除文件或者文件夹
注意:
① 如果删除文件,不在回收站
② 如果删除文件夹,必须是空的文件夹

boolean isDirectiry():判断是否是文件夹
boolean isFile():判断是否是文件
boolean exists():判断文件或文件夹是否存在

String[] list():遍历指定的文件夹,返回的是String数组
File[] listFiles():遍历指定的文件夹,返回的是File数组
注意点:
listFiles方法底层还是list方法

package alive.a_flie;

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

/**
 * @Author zyj
 * @Date 2024/09/19 10:16
 * @Description
 */
public class Test {
    public static void main(String[] args) throws IOException {
        File f1 = new File("D:\\code\\alive\\2.text");
        System.out.println("file = " + f1);
        boolean newFile = f1.createNewFile();
        System.out.println("newFile = " + newFile);
        File f2 = new File("D:\\code\\alive\\2");
        boolean mkdir = f2.mkdir();
        System.out.println("mkdir = " + mkdir);
        System.out.println("f2.isDirectory() = " + f2.isDirectory());
        System.out.println("f1.isFile() = " + f1.isFile());
        boolean d1 = f1.delete();
        System.out.println("del = " + d1);
        boolean d2 = f2.delete();
        System.out.println("d1 = " + d1);
        System.out.println("d2 = " + d2);
        System.out.println("f1.exists() = " + f1.exists());
        //file = D:\code\alive\2.text
        //newFile = true
        //mkdir = true
        //f2.isDirectory() = true
        //f1.isFile() = true
        //del = true
        //d1 = true
        //d2 = true
        //f1.exists() = false
        File f3 = new File("D:\\code\\alive");
        String[] list = f3.list();
        for (String s : list) {
            System.out.println("s = " + s);
        }
        File[] files = f3.listFiles();
        for (File file : files) {
            System.out.println("file = " + file);
        }
        //s = alive-service
        //s = javaSE
        //s = owner_webapp
        //s = test.txt
        //s = 需求文档.md
        //file = D:\code\alive\alive-service
        //file = D:\code\alive\javaSE
        //file = D:\code\alive\owner_webapp
        //file = D:\code\alive\test.txt
        //file = D:\code\alive\需求文档.md
        
    }
}

练习

查询目录下的所有文件

package alive.b_flie;

import java.io.File;

/**
 * @Author zyj
 * @Date 2024/09/19 16:12
 * @Description
 */
public class Test {
    public static void main(String[] args) {
        showAllFiles(new File("D:\\code\\alive"));
    }

    private static void showAllFiles(File file) {
        for (File f : file.listFiles()) {
            if (f.isFile()) {
                System.out.println(f.getName());
            } else {
                showAllFiles(f);
            }
        }
    }
}

相对路径和绝对路径

① 绝对路径:从盘符开始写的路径;
D:\code\alive
② 相对路径:不从盘符名开始写的路径
哪个路径是参照路径,哪个路径就可以省略不写,剩下的就是在idea中的相对路径写法
在idea中参照路径就是当前project的绝对路径
在这里插入图片描述
绝对路径:D:\code\alive\javaSE\file\test.txt
相对路径:file\test.txt

在idea中写相对路径,其实就是从模块名中写
如果直接写文件名默认是在工程更目录下

IO流

什么是IO流

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象
流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便直观的进行数据操作

IO流分类

  • 按照流的流向分类

输入流InputStream:表示将数据读取到Java程序(内存)中使用的流;
输出流OutputSteam:表示从Java程序(内存)向外传输使用的流;

  • 按照流的数据单位分

字节流:万能流,一切皆字节,一次性传输一个字节数据,将数据以字节的形式传输;
字符流:操作文本文档,一次性传输一个字符数据,将数据以字符的形式传输;

  • 按照流的层次分

节点流:可以从或向一个特点的节点读写数据
处理流:是对一个已存在的流连接和封装,通过所封装的流的功能调用实现数据读写

字节输出流(OutputSteam)

① 字节输出流OutputStream是一个抽象类
子类:FileOutputStream
② 构造:
FileOutputStream(File file)
FileOutputStream(String name)
③ 特点:
指定的文件没有,则会自动创建;
每执行一次,默认都会创建一个新的文件,覆盖旧的文件

方法:
void write(int b):一次写一个字节
void write(byte[] b):一次写一个字节数组
void write(byte[] b,int off,int len):一次写一个字节数组的一部分,b:写的数组, off:从数组的哪个索引开始写 len:写多少个
void close():关闭资源

package alive.c_io;

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

/**
 * @Author zyj
 * @Date 2024/09/19 16:57
 * @Description
 */
public class Test {
    public static void main(String[] args) throws IOException {
        FileOutputStream outputStream = new FileOutputStream("file/test.txt");
        outputStream.write(98);
        byte[] bytes = {97, 98, 99, 100, 101, 102, 103};
        outputStream.write(bytes);
        outputStream.write(bytes, 0, 2);
        byte[] strBytes = "张云进".getBytes();
        FileOutputStream outputStream2 = new FileOutputStream("file\\test1.txt");
        outputStream2.write(strBytes);
        outputStream.close();
    }
}

FileOutputStream(String name,boolean append):会实现内容追加,不会覆盖原始内容;
\r\n(window):换行占两个字节
\n(linux)
\r(macOS)

字节输入流(InputStream)

InputStream,是一个抽象类
子类:FileInputStream

读数据,将数据读到内存中

FileInputStream(File file)
FileInputStream(String name)
方法:
int read():一次读一个字节,返回的是读取的字节
int read(byte[] b):一次读取一个字节数组,返回的是读取的字节个数
int read(byte[] b,int off,int len):一次读取一个字节数组的一部分
void close():关闭资源

package alive.d_io;

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

/**
 * @Author zyj
 * @Date 2024/09/19 18:06
 * @Description
 */
public class Test {
    public static void main(String[] args) throws IOException {
        FileInputStream inputStream = new FileInputStream("file\\test1.txt");
//        int r1 = inputStream.read();
//        System.out.println("r1 = " + r1);
//        int r2 = inputStream.read();
//        System.out.println("r2 = " + r2);
//        int r3 = inputStream.read();
//        System.out.println("r3 = " + r3);
//        int r4 = inputStream.read();
//        System.out.println("r4 = " + r4);
//        int r5 = inputStream.read();
//        System.out.println("r4 = " + r5);
//        r1 = 98
//        r2 = 97
//        r3 = 98
//        r4 = 99
//        r4 = -1
        int len;
        while ((len = inputStream.read()) != -1) {
            System.out.println("==>" + (char) len);
        }
        inputStream.close();
    }
}

每个文件末尾都一个结束标记,read读到结束标记则返回-1

    package alive.d_io;

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

/**
 * @Author zyj
 * @Date 2024/09/19 18:06
 * @Description
 */
public class Test {
    public static void main(String[] args) throws IOException {
        FileInputStream inputStream = new FileInputStream("file\\test1.txt");
        byte[] bytes = new byte[2];
        int length;
        while ((length = inputStream.read(bytes)) != -1) {
            System.out.println(new String(bytes, 0, length));
        }
        inputStream.close();
        //aa
        //ab
        //bb
        //cc
        //c
    }
}

① 创建的数组相当于一个临时存储区域,我们要读取的内容会临时保存到数组中,然后再从数组中获取
② 数组的长度定多少,每次就能读取多少,一般情况下数组长度定为1024或者1024的倍数,如果剩余未读字节数不够数组长度,那么能读取多少就读多少

练习1

package alive.e_io;

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

/**
 * @Author zyj
 * @Date 2024/09/20 10:45
 * @Description
 */
public class Test {
    public static void main(String[] args) throws IOException {
        FileInputStream is = new FileInputStream("file\\dog.png");
        FileOutputStream os = new FileOutputStream("file\\copyDog.png");

        int read;
        while ((read = is.read()) != -1) {
            System.out.println(read);
            os.write(read);
        }
        os.close();
        is.close();
    }
}

字符输入流 FileReader

字符流用来操作文本文档,Reader是一个抽象类
子类:FileReader

UTF-8:一个中文占三个字节
GBK:一个中文占两个字节
复制使用字节流不使用字符流
作用:
将文本文档中的内容读取到内存中的类

FileReader(File file)
FileReader(String path)

方法:
int read():一次读取一个字符,返回的是字符对应的int值
int read(char[] cbuf):一次读取一个字符数组,返回读取个数
int read(char[] cbuf,int off, int len):一次读取一个字符数组的一部分,返回的是读取个数
void close():关闭资源

package alive.f_fliereader;

import java.io.FileReader;

/**
 * @Author zyj
 * @Date 2024/09/20 15:41
 * @Description
 */
public class Test {
    public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("file\\test.txt");
//        int read = fr.read();
//        System.out.println("read = " + read);
//        System.out.println("(char)read = " + (char) read);
        //read = 20808
        //(char)read = 先
//        int res;
//        while ((res = fr.read()) != -1) {
//            System.out.print((char) res);
//        }
        char[] ch = new char[1024];
        int res;
        while ((res = fr.read(ch)) != -1) {
            System.out.println(new String(ch, 0, res));
        }

        fr.close();
    }
}

字符输出流 FileWriter

① 字符输出流writer抽象类
子类:FileWriter
② 将数据写到文件中
③ 构造:
FileWriter(File file)
FileWriter(String fileName)
FileWriter(String filename,blooean append)
④ 方法:
void write (int c):一次写入一个字符
void write (char[] cbuf):一次写入一个字符数组
void write (char[] cbuf,int off,int len):一次写入数组的一部分
void write (String str):写入字符串
void flush:将缓冲区中的数据刷到文件中
void close():关闭流

注意点:
FileWriter底层自带一个缓冲区,我们写的数据会先保存到缓冲区中,所以我们先将缓冲区中的数据写到文件中

IO流异常处理

package alive.h_exception;

import java.io.FileWriter;
import java.io.IOException;

/**
 * @Author zyj
 * @Date 2024/09/20 16:31
 * @Description
 */
public class Test {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("file\\test2.txt");
            fw.write("hello");
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (fw != null) {
                try {
                    fw.close();
                } catch (IOException ex) {
                    throw new RuntimeException(ex);
                }
            }
        }
    }
}

JDK7 后的写法

package alive.h_exception;

import java.io.FileReader;
import java.io.FileWriter;

/**
 * @Author zyj
 * @Date 2024/09/20 16:31
 * @Description
 */
public class Test {
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("file\\test.txt"); FileWriter fw = new FileWriter("file\\text1.txt")) {
            System.out.println((char) fr.read());
        } catch (Exception e) {

        }
    }
}

使用上面的结构会自动关闭流,无需手动关闭

字节缓冲流

为什么使用字节缓冲流?
FileOutputStream、FileInputStream、FileReader、FileWriter都叫基本类;其中FileInputStream和FileOutputStream的读写方法都是本地方法(native),本地方法是和系统硬盘通信的,两个读写都是硬盘之间进行读写的,效率比较不高;而缓冲流中底层带有一个长度为8192的数组(缓冲区),此时读和写都是在内存(缓冲区)中进行的,读写效率比较高;

使用之前需要将基本流包装成缓冲流,new 对象时,传递基本流

字节缓冲流
BufferedOutputStream:字节缓冲输出流
构造方法:BufferedOutputStream(OutputStream out)
使用:和FileStream一致
BufferedInputStream:字节缓冲输入流
构造方法:BufferedInputStream(InputStream in)
使用:和FileInputStream一致

package alive.i_buffered;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 * @Author zyj
 * @Date 2024/09/20 17:13
 * @Description
 */
public class T1 {
    public static void main(String[] args) {
        baseStream();
        bufferedStream();
    }

    public static void baseStream() {
        long start = System.currentTimeMillis();
        try (FileInputStream fis = new FileInputStream("file\\demo.mp4"); FileOutputStream fos = new FileOutputStream("file\\demo_c.mp4")) {
            int res;
            while ((res = fis.read()) != -1) {
                fos.write(res);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            long end = System.currentTimeMillis();
            System.out.println("字节流使用时间==》" + (end - start));
            //字节流使用时间==》47219
        }
    }

    public static void bufferedStream() {
        long start = System.currentTimeMillis();
        try (FileInputStream fis = new FileInputStream("file\\demo.mp4");
             FileOutputStream fos = new FileOutputStream("file\\demo_b_c.mp4");
             BufferedInputStream bis = new BufferedInputStream(fis);
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            int res;
            while ((res = bis.read()) != -1) {
                bos.write(res);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            long end = System.currentTimeMillis();
            System.out.println("字节流使用时间==》" + (end - start));
            //字节流使用时间==》480
        }
    }
}

关闭原理

在使用缓冲流的时候,为什么只需要关闭缓冲流而不用关闭基本流?
缓冲流的close底层会自动关闭
在这里插入图片描述

读写原理

缓冲流底层有数组(缓冲区),都是在内存之间进行读写,那么缓冲流读写的过程是什么样的?
① 先依靠基本流将数据读出来,交给缓冲流,由于缓冲流缓冲区8192,所以每次读取8192个字节放到缓冲区中
② 等待输出流缓冲区填满,再依靠基本流写入硬盘
③ 如果输入流缓冲区中的数据读不到了,重新从硬盘上读8192个字节,进入到输入流缓冲区中,继续利用len在两个缓冲区之间来回传递值
在这里插入图片描述

字符缓冲流

字符流的基本流底层是有缓冲区的,所以效率不是特别明显

字符缓冲输出流(BufferedWriter)

构造
BufferedWriter(Writer w)

newLine():换行

package alive.i_buffered;

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

/**
 * @Author zyj
 * @Date 2024/09/20 17:53
 * @Description
 */
public class T2 {
    public static void main(String[] args) throws IOException {
        BufferedWriter bfw = new BufferedWriter(new FileWriter("file\\text1.txt", true));
        bfw.write("静止了所有的花开");
        bfw.newLine();
        bfw.write("遥远了清晰了爱");
        bfw.newLine();
        bfw.write("天郁闷爱却很喜欢");
        bfw.newLine();
        bfw.write("那时候我不懂着叫爱");
        bfw.close();
    }
}

字符缓冲输入流(BufferedReader)

构造
BufferedReader(Reader r)

String readLine():一次读一行,如果读到结束表姐,返回null

package alive.i_buffered;

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

/**
 * @Author zyj
 * @Date 2024/09/21 14:05
 * @Description
 */
public class T3 {
    public static void main(String[] args) throws IOException {
        BufferedReader bfr = new BufferedReader(new FileReader("file\\text1.txt"));
        String str = null;
        while ((str = bfr.readLine()) != null) {
            System.out.println("str = " + str);
        }
        bfr.close();
    }
}

字符编码

计算机中存储的信息都是二进制数表示的,我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制转换之后的结果。【按照某种规则,将字符存储到计算机中,称为编码】。反之,将存储在计算机中的二进制按照某种规则解析显示出来,称为解码。比如,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本符号,反之,按照A规则存储,再按照B规则解析,就会出现乱码现象。

  • 字符编码Character Encoding:是一套自然语言的字符与二进制数之间的对应规则

字符集

字符集Charset:编码表,是一个系统支持的所有字符的集合,包括各国家文字,标点符号,图形符号、数字等。
计算机要准确的存储和识别各种字符集编号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASII字符集、GBK字符集、Unicode字符集等。
在这里插入图片描述

  • ACII字符集

    • ACII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格键、换行键)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。
    • 基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符,ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。
  • ISO-8859-1字符集

    • 拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。
    • ISO-8859-1使用单字节编码,兼容ASII编码
  • GBxxx字符集

    • GB国标的意思,是为了显示中文而的设计一套字符集
    • GB2312:简体中文码表,一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合成包含7000多个简体汉字,此外数字符号、罗马希腊的字母、日文的假名都编进去了,连在ASCII里面本来就有的数字、标点、字母都统统重新编写了两个字节的编码,这就是常说的“全角”字符,而原来在127号以下的那些就叫“半角”字符了
    • GBK:是常用的中文码表,是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等
    • GB18030:最新的中文码表,收录了70244个,采用多字节编码,每个字可以由1个、2个或者4个字节组成。支持中国国内少数民族的文字,同时支持繁体字以及日韩汉字等。
  • Unicode字符集

    • Unicode编码系统为表达任意语言的任意字符而设计的,是业界的一种标准,也称为统一码、标准万国码。
    • 它最多使用4字节的数字来表达每个字母、符号、或者文字。有三种编码方案,UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。
    • UTF-8编码,可以用来表示Unicode标准任何字符,它是电子邮件、网页以及其他存储或者传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求用一至四个字节为每个字符编码,编码规则:
    1. 128个US-ASCII字符,只需一个字节编码
    2. 拉丁文等字符,需要两个字节编码
    3. 大部分常用字(含中文),需要三个字节编码
    4. 其他极少数使用的Unicode辅助字符,使用四个字节编码

转换流

编码规则不一致时,会出现中文乱码

InputStreamReader

字节流通向字符流的桥梁 读数据

InputStreamReader(InputStream in,String charsetName)
charsetName:指定编码,不区分大小写

package alive.j_reversestream;

import java.io.FileInputStream;
import java.io.InputStreamReader;

/**
 * @Author zyj
 * @Date 2024/09/21 15:52
 * @Description
 */
public class T1 {
    public static void main(String[] args) throws Exception {
        InputStreamReader isr = new InputStreamReader(new FileInputStream("file\\text1.txt"), "gbk");
        System.out.println((char) isr.read());
        isr.close();
    }
}

OutputStreamWriter

字符流通向字节流的桥梁

OutputStreamWriter(OutputStream out,String charsetName)

按照指定的编码规则存数据

package alive.j_reversestream;

import java.io.FileOutputStream;
import java.io.OutputStreamWriter;

/**
 * @Author zyj
 * @Date 2024/09/21 23:10
 * @Description
 */
public class T2 {
    public static void main(String[] args) throws Exception {
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("file\\text2.txt"), "gbk");
        osw.write("韩");
        osw.close();
    }
}

序列化流

序列化和反序列化

读写对象

ObjectOutputStream:序列化,写对象
ObjectInputStream:反序列化,读对象

序列化流ObjectOutputStream

写对象
ObjectOutputStream(OutputStream out)
writeObject(Object obj):写对象
将对象写入文件中,别序列化的对象需要实现Serializable接口

package alive.k_serializable;

import java.io.Serializable;

/**
 * @Author zyj
 * @Date 2024/09/22 19:50
 * @Description
 */
public class Person implements Serializable {
    private String name;

    private int age;

    public Person() {
    }

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

    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;
    }

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

package alive.k_serializable;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;

/**
 * @Author zyj
 * @Date 2024/09/22 19:50
 * @Description
 */
public class T1 {
    public static void main(String[] args) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file\\p1.txt"));
        oos.writeObject(new Person("tom", 11));
        oos.close();
    }
}

反序列化ObjectInputStream

读对象
ObjectInputStream(InputStream in)
Object readObject()

package alive.k_serializable;

import java.io.FileInputStream;
import java.io.ObjectInputStream;

/**
 * @Author zyj
 * @Date 2024/09/22 19:50
 * @Description
 */
public class T1 {
    public static void main(String[] args) throws Exception {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file\\p1.txt"));
        Person p = (Person) ois.readObject();
        System.out.println("p = " + p);
        ois.close();
    }
}

transient

使用关键字transient修饰属性,此属性不能被序列化

private transient int age;

反序列化异常处理

  • 序列化之后,修改源码后没有序列化而直接反序列化,会出现序列号冲突问题
  • 在这里插入图片描述

在这里插入图片描述

将序列化固化,序列化不变
在对象加入``public static final long 的变量,并为其赋值

public static final long serialVersionUID = 42L;

将一个对象实现序列化接口,才能让这个对象以二进制的形式在网络中传输

  • 遍历读取和存储多个对象
package alive.k_serializable;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

/**
 * @Author zyj
 * @Date 2024/09/22 19:50
 * @Description
 */
public class T1 {
    public static void main(String[] args) throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("file\\p1.txt"));
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("Jack", 19));
        list.add(new Person("Tom", 10));
        list.add(new Person("Alex", 23));
        oos.writeObject(list);
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("file\\p1.txt"));
        ArrayList<Person> persons = (ArrayList<Person>) ois.readObject();
        System.out.println("persons = " + persons);
        oos.close();
        ois.close();
    }
}

打印流PrintStream

new PrintStream(String fileName)

println(String str):打印输出,换行
print(String str):打印输出,不换行

package alive.l_printstream;

import java.io.FileNotFoundException;
import java.io.PrintStream;

/**
 * @Author zyj
 * @Date 2024/09/23 15:05
 * @Description
 */
public class T1 {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = new PrintStream("file\\print.txt");
        ps.println("hello word");
        ps.print("hello word");
        ps.print("hello word");
        ps.close();
    }
}

改变流向
System.out.println():本身输出到控制台
改变流向:可以让输出语句从控制台上输出改变成往指定文件中输出

static void setOut(PrintStream out):改变流向,让输出语句从控制台输出转移至指定文件中

package alive.l_printstream;

import java.io.FileNotFoundException;
import java.io.PrintStream;

/**
 * @Author zyj
 * @Date 2024/09/24 10:54
 * @Description
 */
public class T2 {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = new PrintStream("file\\log.txt");
        System.setOut(ps);
        System.out.println("2024年9月24日10:56:32");
        System.out.println("hello word");
        ps.close();
    }
}

在这里插入图片描述

使用场景:
可以将输出的内容以及详细信息放到日志文件中,永久保存

打印流续写

package alive.l_printstream;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;

/**
 * @Author zyj
 * @Date 2024/09/24 11:04
 * @Description
 */
public class T3 {
    public static void main(String[] args) throws FileNotFoundException {
        PrintStream ps = new PrintStream(new FileOutputStream("file\\log.txt", true));
        System.setOut(ps);
        System.out.println("追加的内容A");
        System.out.println("追加的内容B");
        System.out.println("追加的内容C");
        System.out.println("追加的内容D");
        System.out.println("追加的内容E");
        ps.close();
    }
}

Properties集合

使用场景在配置文件中使用
在这里插入图片描述

package alive.m_properties;

import java.io.FileInputStream;
import java.util.Properties;
import java.util.Set;

/**
 * @Author zyj
 * @Date 2024/09/24 11:11
 * @Description
 */
public class T1 {
    public static void main(String[] args) throws Exception {
        Properties properties = new Properties();
        FileInputStream fis = new FileInputStream("file\\jdbc.properties");
        properties.load(fis);
        Set<String> set = properties.stringPropertyNames();
        for (String key : set) {
            System.out.println(key + "->" + properties.getProperty(key));
        }
    }
}

Commons-io工具包

IO 技术开发中,代码量很大, 而且代码的重复率很高,如果我们要遍历目录,拷贝目录就需要使用方法递归调用,也增大了程序的复杂度。
Apache软件基金会,开发了IO技术的工具类commonIO,大大简化了IO开发

https://commons.apache.org/io/download_io.cgi

导入Jar包
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

工具包的使用

IOUtils类

  • 静态方法:IOUtils.copy(InputStream in,OutputStream out)传递字节流,实现文件复制
  • 静态方法:IOUtils.closeQuietly(任意流对象)自动释放资源,自动处理close()方法抛出的异常
package alive.n_utils;


import org.apache.commons.io.IOUtils;

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

/**
 * @Author zyj
 * @Date 2024/09/24 11:50
 * @Description
 */
public class T1 {
    public static void main(String[] args) throws IOException {
        IOUtils.copy(new FileInputStream("file\\demo.mp4"), new FileOutputStream("file\\demo_dd.mp4"));
    }
}

package alive.n_utils;
import org.apache.commons.io.IOUtils;
import java.io.FileWriter;

/**
 * @Author zyj
 * @Date 2024/09/24 13:44
 * @Description
 */
public class T2 {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("file\\text1.txt");
            fw.write("hello");
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(fw != null){
                IOUtils.closeQuietly(fw);
            }
        }
    }
}

FileUtils类

  • 静态方法
    FileUtils.copyDirectoryToDirectory(File src,File dest)
    传递File类型的目录,进行整个目录的复制,自动进行递归遍历。
    参数:src - 要复制的文件夹目录
    dest:将文件复制到目标
    writeStringToFile(File file,String str):写字符串到文本文件中。
    String readFileToString(File file):读取文本文件,返回字符串
package alive.n_utils;

import org.apache.commons.io.FileUtils;

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

/**
 * @Author zyj
 * @Date 2024/09/24 13:53
 * @Description
 */
public class T3 {
    public static void main(String[] args) throws IOException {
        FileUtils.copyDirectoryToDirectory(new File("file\\test"), new File("file\\test_copy"));
        String str = FileUtils.readFileToString(new File("file\\test.txt"));
        System.out.println("str = " + str);
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值