File 类基本使用

java.io.File 类是在 Java 中唯一一个与文件本身有关的程序类,利用这个类用户可以实现文件或目录的处理操作,而使用这个类进行具体的操作前一定要获取一个执行的处理路径。

File 类的定义

public class File
extends Object
implements Serializable, Comparable<File>
方法描述
public File(String pathname)设置要操作文件的完整路径
public File(String parent, String child)设置文件的父目录和子文件路径
public boolean createNewFile() throws IOException创建一个新文件
public boolean delete()文件删除操作
public boolean exists()判断文件是否存在

路径分隔符问题:Windows 系统中,默认的路径分隔符为 \\,但是后来由于 Windows 系统的不断完善,也可以接受 / 分割;Linux 系统中,路径分隔符为 /

为了解决分隔符统一操作问题,在 File 类中提供了一个重要的常量:

public static final String separator

这个常量会根据不同的操作系统有不同的定义,在 Windows 下为 Windows 分隔符,在 Linux 下为 Linux 分隔符。

public class FileDemo {
    public static void main(String[] args) throws IOException {
//        File file = new File("E:\\FileTest\\test.txt");
        File file = new File("E:" + File.separator + "FileTest" + File.separator + "test.txt");
        if (file.exists()) {
            System.out.println("【文件存在,执行删除操作】");
            file.delete();
        } else {
            System.out.println("【文件不存在,执行创建操作】");
            file.createNewFile();
        }
    }
}

文件目录操作

方法描述
public boolean mkdir()创建单级目录
public boolean mkdirs()创建多级目录
public String getParent()获取父路径
public File getParentFile()获取父路径对应的文件对象
public class FileDemo {
    public static void main(String[] args) throws IOException {
//        File file = new File("E:\\FileTest\\test.txt");
        File file = new File("E:" + File.separator + "FileTest" + File.separator + "FileTestChild" + File.separator + "test.txt");
        System.out.println("【文件路径】" + file);
        if (!file.getParentFile().exists()) { // 父路径不存在
            file.getParentFile().mkdir(); // 创建父目录
        }
        if (file.exists()) {
            System.out.println("【文件存在,执行删除操作】");
            file.delete();
        } else {
            System.out.println("【文件不存在,执行创建操作】");
            file.createNewFile();
        }
    }
}

输出:
【文件路径】E:\FileTest\FileTestChild\test.txt
【文件不存在,执行创建操作】

对于当前给定的程序代码如果从性能上来考虑,对于操作目录是否存在的需求最佳的做法是在整个程序运行过程中只进行一次的判断与创建,要想实现这样的目的,可以通过静态代码块的形式完成。

public class FileDemo {
    private static File parentFile = new File("E:" + File.separator + "FileTest" + File.separator + "FileTestChild" + File.separator);

    static { // 静态代码块,优先于主方法执行
        System.out.println("【文件路径】" + parentFile);
        if (!parentFile.getParentFile().exists()) { // 父路径不存在
            parentFile.getParentFile().mkdir(); // 创建父目录
        }
    }

    public static void main(String[] args) throws IOException {
//        File file = new File("E:\\FileTest\\test.txt");
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                File file = new File("E:" + File.separator + "FileTest" + File.separator + "FileTestChild" + File.separator + Thread.currentThread().getName() + ".txt");
                if (file.exists()) {
                    System.out.println("【文件存在,执行删除操作】");
                    file.delete();
                } else {
                    System.out.println("【文件不存在,执行创建操作】");
                    try {
                        file.createNewFile();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }, "Jade-" + i).start();
        }
    }
}

获取文件信息

方法描述
public boolean canExecute()判断当前的路径是否拥有可执行权限
public boolean canRead()判断当前路径是否拥有可读的权限
public boolean canWrite()判断当前路径是否拥有可写的权限
public File getAbsoluteFile()获取文件绝对路径实例
public String getAbsolutePath()获取文件绝对路径字符串
public String getName()获取路径名称
public boolean isAbsolute()是否为绝对路径
public boolean isDirectory()是否为目录
public boolean isFile()是否为文件
public long lastModified()获取最后一次修改日期
public boolean isHidden()是否为隐藏文件或目录
public long length()获取文件长度(单位为字节)
public class FileDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("E:" + File.separator + "Picture" + File.separator + "bg1.jpg");
        if (file.exists()) {
            System.out.print(String.format("【文件大小】字节:%s、%5.2f兆\n", file.length(), (double) file.length() / 1024 / 1024));
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            System.out.print(String.format("【最后一次修改日期】日期时间数值:%s、日期时间:%s\n", file.lastModified(), simpleDateFormat.format(file.lastModified())));
            System.out.print(String.format("【文件权限】可读:%s、可写:%s、可执行:%s\n", file.canRead(), file.canWrite(), file.canExecute()));
            System.out.println("【文件绝对路径】" + file.getAbsolutePath());
            System.out.println("【文件目录】" + file.getParent());
            System.out.println("【文件名称】" + file.getName());
            System.out.printf(String.format("【路径类型】文件夹:%s、文件:%s\n", file.isDirectory(), file.isFile()));
        }
    }
}

输出:
【文件大小】字节:47332804.51兆
【最后一次修改日期】日期时间数值:1604413225769、日期时间:2020-11-03 22:20:25
【文件权限】可读:true、可写:true、可执行:true
【文件绝对路径】E:\Picture\bg1.jpg
【文件目录】E:\Picture
【文件名称】bg1.jpg
【路径类型】文件夹:false、文件:true

获取目录信息

方法描述
public String[] list()列出所有的子路径名称
public File[] listFiles()列出所有子路径的 File 对象数组
public File[] listFiles(FileFilter filter)列出目录组成的时候设置一个判断的过滤器
public class FileDemo {
    public static void main(String[] args) {
        File file = new File("E:" + File.separator + "FileTest" + File.separator);
        if (file.exists() && file.isDirectory()) {
            System.out.println("【list() 方法执行结果】" + Arrays.toString(file.list()));
            System.out.println("【listFiles() 方法执行结果】" + Arrays.toString(file.listFiles()));
        }
    }
}

输出:
【list() 方法执行结果】[FileTestChild, jade.txt]listFiles() 方法执行结果】[E:\FileTest\FileTestChild, E:\FileTest\jade.txt]

如果使用的是 list() 方法实际上所列出的内容仅仅是子路径下的名称而已,而 listFiles() 方法列出的是将子路径转为对应的 File 类对象实例。

列出一个指定目录下的全部的 .txt 文件

public class FileDemo {
    public static void main(String[] args) {
        File file = new File("E:" + File.separator + "FileTest" + File.separator);
        info(file);
    }

    public static void info(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles(f -> f.isDirectory() || f.getName().endsWith(".txt")); // 列出目录中的全部组成
            if (files != null) { // 存在文件列表
                for (File tmp : files) {
                    info(tmp); // 递归操作,继续列出
                }
            }
        } else {
            System.out.println(file); // 执行输出文件信息
        }
    }
}

如果要实现目录中的全部子文件信息的列出,就必须考虑目录下还有子目录的处理问题,所以此时最佳的方法就是判断给出的路径是否为目录,如果为目录则继续进行目录的列出,可以考虑通过递归的形式完成处理。

文件更名

public boolean renameTo(File dest)

如果要进行更名则一定要配置一个完善的路径才可以实现更名处理。

public class FileDemo {
    public static void main(String[] args) {
        File oldFile = new File("E:" + File.separator + "FileTest" + File.separator + "jade.txt");
        File newFile = new File("E:" + File.separator + "FileTest" + File.separator + "bamboo.txt");
        System.out.println("【文件更名处理】" + oldFile.renameTo(newFile));
    }
}

renameTo() 方法除了可以更名之外还可以实现文件的移动操作。

现在有一个数据采集的目录,在目录中所有的日志文件的命名结构为 “jade-日期时间-编号.log” ,以这种操作方式实现一堆文件的生成

public class FileDemo {
    private static File dir = new File("E:" + File.separator + "FileTest" + File.separator + "logs" + File.separator);

    static {
        if (!dir.exists()) {
            dir.mkdir();
        }
    }

    public static void main(String[] args) throws IOException {
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
        for (int i = 0; i < 100; i++) {
            File file = new File(dir, "jade-" + format.format(new Date()) + "-" + i + ".log");
            file.createNewFile();
        }
    }
}

此时需要将所有序号的长度设置为统一的位数,这个位数由文件的数量动态决定,如果有上千个文件,则序号长度为4位;如果有上万个文件,则序号长度为5位。同时这些文件可能保存在不同的目录中。

class DirRenameUtil { // 定义一个专属的命名工具类
    private File dir;// 需要明确知道当前操作的目录地址
    private int sequenceLength; // 保存整体的文件编号的最大长度
    private int fileCount; // 文件个数

    public DirRenameUtil(File dir) {
        this.dir = dir;
        calcFileCount(dir); // 统计文件个数
        sequenceLength = String.valueOf(this.fileCount).length();// 获取文件编号最大长度
    }

    public void rename() {
        this.renameHandler(this.dir);
    }

    private void renameHandler(File file) {
        if (file.isDirectory()) {
            File[] list = file.listFiles();// 列出全部的子路径
            if (list != null) {
                for (File sub : list) {
                    this.renameHandler(sub);
                }
            }
        } else {
            if (file.isFile()) { // 当前路径是文件
                String seq = file.getName().substring(file.getName().lastIndexOf("-") + 1, file.getName().indexOf(".log")); // 中间序号
                if (seq.length() != this.sequenceLength) { // 当前序号是否满足最大序号长度
                    String newFile = file.getName().substring(0, file.getName().lastIndexOf("-") + 1) + addZero(seq) + ".log";
//                    System.out.println(dir + File.separator + newFile);
                    file.renameTo(new File(this.dir + File.separator + newFile));// 更名处理,由于会忽略 dir 最后的分隔符,所以这里要加上分隔符
                }
            }
        }
    }

    private String addZero(String val) {
        StringBuffer buffer = new StringBuffer(val);
        while (buffer.length() != this.sequenceLength) { // 还可以继续添加 0
            buffer.insert(0, "0"); // 在前面补 0
        }
        return buffer.toString();
    }

    private void calcFileCount(File file) { // 统计文件的数量
        if (file.isDirectory()) {
            File[] list = file.listFiles();// 列出全部的子路径
            if (list != null) {
                for (File sub : list) {
                    calcFileCount(sub);
                }
            }
        } else {
            if (file.isFile()) { // 当前路径是文件
                this.fileCount++; // 文件个数增加
            }
        }
    }
}

public class FileDemo {
    public static void main(String[] args) {
        File dir = new File("E:" + File.separator + "FileTest" + File.separator + "logs" + File.separator);
        System.out.println(dir); // 注意输出为 E:\FileTest\logs,会忽略最后的分隔符
        new DirRenameUtil(dir).rename();
    }
}

版权声明:本文为butbabuc原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。