File类

1. File类的基本使用

File,是文件和目录路径的抽象表示 File只关注文件本身的信息,而不能操作文件里的内容

package com.wz.file03_class;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class test01 {
    public static void main(String[] args) {
        //通过指定路径来构建一个文件信息对象
        File file = new File("D:\\Alibaba Cloud disk Download\\test.txt");
        //检测文件是否存在
        System.out.println(file.exists());
        //获取文件的长度(大小,单位:字节)
        long length = file.length();
        System.out.println(length);
        //获取文件最后修改的时间
        long time = file.lastModified();
        System.out.println(time);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(format.format(new Date(time)));
        //获取文件权限
        boolean readable = file.canRead();
        boolean writeable = file.canWrite();
        boolean executeable = file.canExecute();
        System.out.println("read: "+readable);
        System.out.println("write: "+writeable);
        System.out.println("execute: "+executeable);
        //获取文件的路径
        String path = file.getPath();
        System.out.println(path);
        //获取父文件夹的路径
        String parent = file.getParent();
        System.out.println(parent);
        //获取父文件夹对象
        File parentFile = file.getParentFile();
        System.out.println(parentFile);
        System.out.println("------------------------");
        File file1 = new File("test.txt");
        System.out.println(file1.exists());
        System.out.println(file1.getPath());
        System.out.println(file1.getAbsolutePath());
        System.out.println("------------------------");
        //检测文件是否是目录
        boolean isDirectory = file1.isDirectory();
        System.out.println(isDirectory);
        //检测文件是否是文件
        boolean isFile = file1.isFile();
        System.out.println(isFile);
        //检测文件是否为隐藏文件
        boolean isHidden = file1.isHidden();
        System.out.println(isHidden);
        /**
         * 文件操作存在一定的逻辑,当我们要写一个文件的时候,必须要保证文件的父级目录
         * 是存在的,如果不存在,则会报错
         */
        File parentDir = new File("d:/test/test01");
        if (!parentDir.exists()){
            parentDir.mkdirs();
        }
        File writeFile = new File(parentDir, "user.txt");
        if (!writeFile.exists()){
            try {
                writeFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

2023年7月10日,File类,IO流_第1张图片

2. 递归

1. 列出一个文件夹里的所有的.class文件

package com.wz.file04_class;

import java.io.File;
import java.io.FileFilter;

public class FileDemo {
    public static void main(String[] args) {
        String path = "D:\\Project file\\fyOfflineCourse\\MyDay01\\out\\production";
        File folder = new File(path);
        findClass(folder);

    }
    /**
     * 列出一个文件夹中所有的.class文件
     */
    private static void findClass(File folder){
        final FileFilter filter = new FileFilter() {
            @Override
            public boolean accept(File f) {
                return f.getName().endsWith(".class")||f.isDirectory();
            }
        };
        //使用文件过滤器来过滤文件,满足条件的才会在数组中出现
        final File[] files = folder.listFiles(filter);
        for (File file : files) {
            if (file.isDirectory()){
                //递归
                findClass(file);
            }else{
                System.out.println(file.getPath());
            }
        }
    }
}

2023年7月10日,File类,IO流_第2张图片

2. 删除文件夹

/**
     * 删除文件夹,需要注意一点:删除文件夹的时候,如果文件夹中存在子文件,那么文件夹
     * 将无法删除,因此,删除文件夹的时候,首先需要将子文件全部删除
     * @param folder 给定一个要删除的文件夹
     */
    private static void deleteFolder(File folder){
        /*`listFiles()` 是一个 Java 文件类(`File`)的方法
        用于获取一个目录下的所有文件和子目录
        该方法返回一个 `File[]` 数组
        该数组包含了目录中的所有文件和子目录。*/
        final File[] files = folder.listFiles();
        //检验files是否为null
        if (files!=null){
            for (File f : files) {
                //判断f是否是一个目录
                if (f.isDirectory()){//是目录
                    deleteFolder(f);//递归
                }else {
                    f.delete();//不是目录就直接删除
                }
            }
        }
        folder.delete();
    }

2023年7月10日,File类,IO流_第3张图片

该方法首先使用 listFiles() 方法获取文件夹中的所有文件和子目录,并将结果存储在一个 File[] 数组中。

然后,通过遍历数组,判断每个文件或子目录是否是一个目录。如果是目录,就递归调用 deleteFolder() 方法来删除子目录。如果是文件,直接调用 delete() 方法删除文件。

最后,删除完所有子文件和子目录后,调用 delete() 方法删除文件夹本身。

请注意,删除文件夹时需要注意一点:如果文件夹中存在子文件或子目录,那么文件夹将无法直接删除。因此,在删除文件夹之前,需要先删除所有子文件和子目录。以上代码中的递归调用 deleteFolder() 方法就是用来删除子文件和子目录的。

另外,为了确保子文件夹和子文件都被删除,我们在删除文件夹本身之前,再次调用 delete() 方法删除文件夹。

3. 扫描文件

/**
     * 扫描文件夹
     * @param folder 给定一个扫描的文件夹
     */
    public static void scanFolder(File folder){
        //listFiles()用于获取一个目录下的所有文件和子目录
        File[] files = folder.listFiles();
        if (files!=null){
            for (File f : files) {
                if (f.isDirectory()){//判断f是否为目录
                    scanFolder(f);//递归
                }else {
                    System.out.println(f.getPath());//不是,获取路径
                }
            }
        }
    }

IO流

2023年7月10日,File类,IO流_第4张图片

2023年7月10日,File类,IO流_第5张图片

磁盘和内存是两个不同的设备,它们之间要实现数据的交互,就必须要建立一条通道,在Java中实现建立这样的通道的是I / O流。

Java 中的 I / O 流是按照数据类型来划分的。

分别是字节流(缓冲流、二进制数据流和对象流)、字符流

字节流

1 .OutputStreamTest输出流(写数据)

package com.wz.io01_class;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

public class OutputStreamTest {
    public static void main(String[] args) {
        String path = "d:/io/output.txt";
        File file = new File(path);
        //判断父级目录是否存在
        File parentFile = file.getParentFile();
        if (!parentFile.exists()){
            parentFile.mkdirs();
        }
        //try-with-resources=>JDK1.7提供的新特性 IO流在使用了之后会自动关闭
        //try-with-resources try后面的()中可以写多行代码,但是必须以分号分割开,最后一行代码的
        //分号可以省略。能够写入括号中的内容必须是实现了AutoClosable接口的流的构建
        try (OutputStream os = new FileOutputStream(file,true)) {
            String content = "hello world!!";
            final byte[] data = content.getBytes();//获取字符串的byte数据
            os.write(data);//写入数据
            os.flush();//强制将通道中的数据刷出,写入文件
        }catch (IOException e){
            e.printStackTrace();
        }

    }
}

2023年7月10日,File类,IO流_第6张图片

以上代码是一个使用 OutputStream 将数据写入文件的示例。

首先,我们创建一个 File 对象,表示要写入的文件。然后,使用 getParentFile() 方法获取父级目录,并判断该目录是否存在。如果不存在,使用 mkdirs() 方法创建父级目录。

接下来,我们使用 FileOutputStream 来创建一个输出流 os,并将文件作为参数传递给它。这样就可以将数据写入文件了。

在写入数据之前,我们将要写入的内容转换为字节数组 data,然后使用 write() 方法将数据写入文件。最后,使用 flush() 方法强制将通道中的数据刷新到文件中。

为了确保流被正确关闭,我们使用了 try-with-resources 语句。在 try 后面的括号中,我们创建了一个 OutputStream 对象,并将其赋值给 os。在 try 代码块结束后,os 将自动关闭。

如果在写入数据过程中发生了异常,我们使用 catch 块捕捉并打印异常信息。

注意,如果要将数据追加到文件末尾而不是覆盖原有内容,可以在创建 FileOutputStream 对象时传入第二个参数 true,如下所示:

OutputStream os = new FileOutputStream(file, true);

2. InputStreamTest输入流

package com.wz.io01_class;

import java.io.*;

public class InputStreamTest {
    public static void main(java.lang.String[] args) {
        File file = new File("d:/io/output.txt");
        try (InputStream in = new FileInputStream(file);){
            //如果文件比较大,我们需要构建一个容器,来反复读取文件内容
            byte[] buffer = new byte[5];
            int len;
            while ((len = in.read(buffer)) != -1){
                System.out.println(new java.lang.String(buffer,0, len));
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}

2023年7月10日,File类,IO流_第7张图片

以上代码是一个使用 InputStream 从文件中读取数据的示例。

首先,我们创建一个 File 对象,表示要读取的文件。然后,使用 FileInputStream 来创建一个输入流 in,并将文件作为参数传递给它。这样就可以从文件中读取数据了。

在读取数据之前,我们创建了一个字节数组 buffer,用于存储读取到的数据。buffer 的大小可以根据需要调整,这里设置为 5 个字节。

然后,我们使用 read() 方法从输入流中读取数据,并将读取到的字节数保存在变量 len 中。如果 len 的值为 -1,表示已经读取到文件末尾,循环结束。否则,我们使用 new String(buffer, 0, len) 将字节数组转换为字符串,并打印出来。

try-with-resources 自动关闭流。

3. 利用io流进行复制

package com.wz.io01_class;

import java.io.*;
import java.nio.file.Files;

public class FileCopy {
    public static void main(String[] args) {
        String source = "d:/io/output.txt";
        String dest = "d:/io/output01.txt";
        copy(new File(source), new File(dest));
    }


    public static void copy(File source, File dest) {
        //获取父目录
        final File parentFile = dest.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        try (InputStream in = Files.newInputStream(source.toPath());
             OutputStream os = Files.newOutputStream(dest.toPath())) {
            byte[] buffer = new byte[2048]; //构建一个容器来存储读取的数据
            int len;
            while ((len = in.read(buffer)) != -1) {
                //读取多少就写多少
                os.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

2023年7月10日,File类,IO流_第8张图片

字节流仅仅适用于读取原始数据(基本数据类型)

字符流

1. 从文件中读取数据并写入另一个文件

package com.wz.char_class;

import java.io.*;

public class ReaderTest {
    public static void main(String[] args) {
        //字符流的顶层父类,Reader Writer
        try(Reader reader = new FileReader("d:/io/output.txt");
            Writer writer = new FileWriter("d:/io/output03.txt")){
            char[] buffer = new char[2048];
            int len;
            while ((len=reader.read(buffer))!=-1){
                System.out.println(new String(buffer,0,len));
                writer.write(buffer,0,len);
            }

        }catch (IOException e){
            e.printStackTrace();
        }
    }
}

2023年7月10日,File类,IO流_第9张图片

以上代码是一个使用字符流 ReaderWriter 从文件中读取数据并写入另一个文件的示例。

首先,我们创建一个 Reader 对象 reader,使用 FileReader 来读取文件 "d:/io/output.txt" 的内容。然后,我们创建一个 Writer 对象 writer,使用 FileWriter 来写入文件 "d:/io/output03.txt"

在读取和写入数据之前,我们创建了一个字符数组 buffer,用于存储读取到的数据。buffer 的大小可以根据需要调整,这里设置为 2048 个字符。

然后,我们使用 read() 方法从输入流中读取数据,并将读取到的字符数保存在变量 len 中。如果 len 的值为 -1,表示已经读取到文件末尾,循环结束。否则,我们使用 new String(buffer, 0, len) 将字符数组转换为字符串,并打印出来。同时,我们使用 write() 方法将读取到的数据写入到输出流中。

2. 字符缓存流

package com.wz.char_class;

import java.io.*;

public class BufferedStreamDemo {
    public static void main(String[] args) {
        try(Reader reader = new FileReader("d:/io/output.txt");
            BufferedReader br = new BufferedReader(reader)){
            //读取一行数据,本质上是一个一个的读取,读取到\r\n就停止

            while (true){
                String s = br.readLine();
                if (s == null){
                    break;
                }
                System.out.println(s);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
        String[] infos = {"第一条数据","第二条数据","第三条数据"};
        try(Writer writer = new FileWriter("d:/io/buffer.txt");
            BufferedWriter bw = new BufferedWriter(writer)){
            for (String info : infos) {
                bw.write(info);//写一个字符串
                //bw.write('\r');
                //bw.write('\n');
                //bw.write("\r\n");
                bw.newLine();//换行
            }

        }catch (IOException e){
            e.printStackTrace();
        }

    }
}

2023年7月10日,File类,IO流_第10张图片

以上代码是一个使用缓冲字符流 BufferedReaderBufferedWriter 的示例。

首先,在 main() 方法中,我们创建一个 Reader 对象 reader,使用 FileReader 来读取文件 "d:/io/output.txt" 的内容。然后,我们创建一个 BufferedReader 对象 br,将 reader 对象传入构造方法中进行包装。

在读取数据时,我们使用 readLine() 方法从输入流中读取一行数据。如果读取到的数据为 null,表示已经读取到文件末尾,循环结束。否则,我们将读取到的数据打印出来。

为了确保流被正确关闭,我们使用了 try-with-resources 语句。在 try 后面的括号中,我们创建了一个 Reader 对象,并将其赋值给 reader,同时创建了一个 BufferedReader 对象,并将其赋值给 br。在 try 代码块结束后,readerbr 将自动关闭。

在第二部分的代码中,我们创建了一个字符串数组 infos,其中包含了三条数据。

然后,我们创建一个 Writer 对象 writer,使用 FileWriter 来写入文件 "d:/io/buffer.txt"。接下来,我们创建一个 BufferedWriter 对象 bw,将 writer 对象传入构造方法中进行包装。

在写入数据时,我们使用 write() 方法将字符串写入输出流中。为了实现换行效果,我们使用了 newLine() 方法来插入换行符。

同样地,为了确保流被正确关闭,我们使用了 try-with-resources 语句。在 try 后面的括号中,我们创建了一个 Writer 对象,并将其赋值给 writer,同时创建了一个 BufferedWriter 对象,并将其赋值给 bw。在 try 代码块结束后,writerbw 将自动关闭。

请注意,BufferedReaderBufferedWriter 可以提供更高效的读写操作,因为它们会在内部维护一个缓冲区,以减少对底层流的直接访问次数。这样可以减少文件读写的开销,提高读写的效率。

应用

在一个文本文件中储存有一下信息:

张三 男 20 李四 女 22 王五 其他 23

由于在录入的时候,王五的性别录成了“其他“

现在需要将性别修正为”男“

请使用IO流的相关知识完成这个过程

package com.wz.char02_class;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

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

        /*在一个文本文件中储存有一下信息
        张三 男  20
        李四 女  22
        王五 其他 23
        由于在录入的时候,王五的性别录成了“其他“
        现在需要将性别修正为”男“
        请使用IO流的相关知识完成这个过程*/
        //构建集合存储文本集合
        List students =new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader("d:/io/test.txt"));){
            String line;
            while ((line=reader.readLine())!=null){
                //根据,号分割字符串
                String[] arr = line.split(",");
                Student stu = new Student();
                stu.setName(arr[0]);
                stu.setSex(arr[1]);
                stu.setAge(Integer.parseInt(arr[2]));
                students.add(stu);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
        try(BufferedWriter writer = new BufferedWriter(new FileWriter("d:/io/test.txt"))){
            //修改集合中的王五的性别
            for (Student student : students) {
                String name = student.getName();
                if ("王五".equals(name)){
                    student.setSex("男");
                }
                writer.write(student.toLine());
                writer.newLine();
            }
            writer.flush();
        }catch (IOException e) {
            e.printStackTrace();
        }

    }
}

2023年7月10日,File类,IO流_第11张图片

以上代码是一个使用缓冲字符流 BufferedReaderBufferedWriter 的示例。

首先,在 main() 方法中,我们创建了一个空的 Student 对象列表 students,用于存储从文件中读取的学生信息。

然后,我们使用 BufferedReaderFileReader 创建了一个读取文件的流 reader,并将其传入 BufferedReader 的构造方法中进行包装。

接下来,我们使用 readLine() 方法从输入流中逐行读取数据。每读取一行数据,我们将其根据逗号分隔成一个字符串数组 arr,然后根据数组中的元素构建一个 Student 对象,并将其添加到 students 列表中。

在读取完文件内容后,我们关闭了 reader 流。

接下来,我们使用 BufferedWriterFileWriter 创建了一个写入文件的流 writer,并将其传入 BufferedWriter 的构造方法中进行包装。

然后,我们遍历 students 列表中的每个 Student 对象。如果学生的名字是 "王五",则将其性别修改为 "男"。

然后,我们使用 write() 方法将学生对象转换为一行字符串,并使用 newLine() 方法插入换行符。最后,我们调用 flush() 方法将缓冲区的内容写入文件,并关闭 writer 流。

这样就完成了将文件中的性别修正为 "男" 的操作。

请注意,在读取文件和写入文件时,我们都使用了缓冲字符流 BufferedReaderBufferedWriter,以提高读写的效率。同时,在使用这些流时,我们使用了 try-with-resources 语句,以确保流被正确关闭。