自学内容网 自学内容网

Java的File类详解

Java语言自从JDK 1.0开始的输入/输出(Input/Output,简称I/O)是同步阻塞式IO(简称BIO)。它使用java.io.File类对象来管理文件和目录。

一、Java File类概述
Java文件类File是java.io包下代表与平台无关的文件和目录,Java程序操作文件和目录,都可以通过File类来完成。但是访问文件内容本身,要通过输入/输出流。
java.io.File类是Java用于处理文件和目录路径的类。它提供了文件和目录的创建、删除、重命名等操作。File类还可以用来获取文件和目录的属性,包括大小、修改时间,以及是否存在、是否可读可写等。
Java是面向对象的语言,因此硬盘中的一个文件在Java中通过文件对象来表示,文件对象所属的类就是File类。File对象代表磁盘中实际存在的文件和目录。

目录路径
在处理文件和目录时,路径有两种不同的表示方式:绝对路径和相对路径。它们在Java中的java.io.File类和其他相关类中经常使用。

  • 绝对路径
    定义:绝对路径是从文件系统的根目录开始的完整路径。它指定了从根目录到文件或目录的确定路径。例如:D:\tmp 或 D:/tmp
    特点:
    不依赖于当前工作目录。
    总是以根目录(如Windows中的盘符C:\、D:\,或Unix/Linux中的/)开始。
    在不同的平台(操作系统)的文件系统之间通常不可移植。

  • 相对路径
    定义:相对路径是相对于当前工作目录的路径。它只指定从当前目录开始的局部路径。例如:.\test.txt 或 ./test.txt
    特点:
    依赖于当前工作目录。
    不以根目录开始。
    在不同的平台之间更易于移植。

  • 当前路径
    当前路径就是指当前工作目录的路径:在Java中,当前工作目录通常是启动Java虚拟机时的工作目录。你可以使用System.getProperty(“user.dir”)来获取当前工作目录的路径。

注意事项
路径分隔符:Windows系统使用反斜杠“\”作为路径分隔符,而Unix/Linux系统使用斜杠“/”。
反斜杠“\”在Java正则表达式中是元字符,它有特殊含义。在 Windows 的路径中反斜杠“\”需要转义处理用“\”表示。
Java 程序支持将斜杠“/”作为与平台无关的路径分隔符,Windows平台也适用。
在Java中,你也可以使用File.separator来获取当前系统的路径分隔符,以确保跨平台兼容性。

文件过滤器
File的list()方法和listFiles()方法可以列出目录的内容(包含子目录和文件),当需要筛选时,就需要过滤。
使用list()方法时,可以传入一个FilenameFilter的实现类,它可以根据文件名过滤文件。
使用listFiles()方法时,可以传入一个FileFiter的实现类,它可以根据文件的自有信息过滤(参数是一个对象,你可以自定义使用什么信息来过滤)
FilenameFilter是一个接口,实现它的类可以根据文件名进行过滤,它里面需要实现一个函数–accept(File dir, String name)方法,第一个参数是过滤的File对象的父目录,第二个参数是文件名或文件夹名。因为传入了文件名或文件夹名参数,所以我们才可以去进行文件名过滤。当返回true时,符合过滤条件。
文件名过滤器的演示例程:

package file;
import java.io.File;
import java.io.FilenameFilter;
public class FilenameFilterDemo {
public static void main(String[] args) {
File file = new File("D:/src");
String[] list = file.list(new FilterBySuffix());
for(String fName : list){
System.out.println(fName);
}
}
}

class FilterBySuffix implements FilenameFilter {

@Override
public boolean accept(File dir, String name) {
return name.endsWith(".mp3");
}
}

FileFiter是一个接口,实现它的类可以根据文件的类型过滤。它里面需要实现一个函数–accept(File pathname)方法,参数pathname是完整的文件路径。当返回true时,符合过滤条件。
文件过滤器的演示例程:

package file;

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

public class FileFilterDemo {

public static void main(String[] args) {
File file = new File("D:/src");
File[] list = file.listFiles(new FilterByType());
for(File f : list){
System.out.println(f);
}
}

}

class FilterByType implements FileFilter {
@Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
}

二、Java File类的构造器
Java的File类有多个重载构造器,以下是四种构造器:

File(File parent, String child) //通过给定的父抽象路径名和子路径名字符串创建一个新的File实例。
File(String pathname)  //通过将给定路径名字符串转换成抽象路径名来创建一个新 File 实例
File(String parent, String child) //根据 parent 路径名字符串和 child 路径名字符串创建一个新 File 实例。
File(URI uri) //通过将给定的 file: URI 转换成一个抽象路径名来创建一个新的 File 实例。

File对象创建示例:

/***根据给定的路径名字符串创建 File 对象***/
// 路径和文件名
String pathname = "D:\\home\\mixia\\java.txt";
// 创建 File实例
File f1 = new File(pathname);
System.out.println(f1);// 输出: D:\home\mixia\java.txt

/***根据父目录路径名和子文件或目录名创建 File 对象***/
// 路径
String path = "D:\\home\\mixia";
// 文件名
String fileName = "java.txt";
// 创建 File实例
File file = new File(path, fileName);
System.out.println(file);// 输出:D:\home\mixia\java.txt

/***根据父 File 对象和子文件或目录名创建 File 对象***/
// 创建 父File对象
File f1 = new File("D:\\home\\mixia");
// 创建 File实例
File f2 = new File(f1, "java.txt");
System.out.println(f2);//输出: D:\home\mixia\java.txt

URI介绍
资源网络地址URL:在互联网上,每一信息资源都有统一的网上地址,该地址称为URL(Uniform Resource Locator,统一资源定位器),它是互联网的统一资源定位标志,俗称“网络地址”。
URL是URI的一个子集,一般用于表示互联网上的资源网络地址。
URI可以直接作为参数传递给File()构造器创建File实例。

        // 假设文件路径为"D:/temp/test.txt"
        String filePath = "file:///D:/temp/test.txt";
        URL url = new URL(filePath); // 创建URL对象
        File file = new File(url.toURI()); //通过URL创建File对象

下面的示例,通过调用URL对象的toURI()方法将其转换为一个java.net.URI对象,再通过URI对象创建了一个File对象。
注意: 文件路径应该使用URL编码格式,例如,空格应该使用%20替换。

用URL转换成URI,再创建File实例的完整示例:

/***根据 file: URI创建 File 对象***/
package nio;
import java.io.File;
import java.net.URI;
import java.net.URL;
public class FileFromURIExample {

public static void main(String[] args) throws Exception {
        // 假设文件路径为"D:/temp/test.txt"
        String filePath = "file:///D:/temp/test.txt";
        // 创建URL对象
        URL url = new URL(filePath);
        // 通过URL获取File对象
        File file = new File(url.toURI());
        // 输出文件路径
        System.out.println("File path: " + file.getAbsolutePath());
        
        // 假设文件路径为"D:/Temp/image/c.txt"
URI resource = URI.create("file:/D:/Temp/image/c.txt");
File file2 = new File(resource);
        // 输出File对象的信息
        System.out.println("File path: " + file2.getPath());
        System.out.println("File name: " + file2.getName());
}
}

三、File类的常用方法
File类提供了文件和目录的创建、删除、重命名等操作。File类还可以用来获取文件和目录的属性,包括大小、修改时间,以及是否存在、是否可读可写等。
File类的方法按照用途的不同大致可分为:文件创建和重命名操作、文件目录操作、文件目录相关属性查询和其他操作。

(一)、文件创建和重命名操作的方法:

  • boolean createNewFile():创建一个新文件
    如果文件不存在,该方法将创建一个新文件,并返回 true;
    如果文件已存在,则不创建新文件,并返回 false。
    这个方法常用于确保不会覆盖已存在的文件,同时创建新文件。
  • File createTempFile(String prefix, String suffix) throws IOException
    在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称。
  • File createTempFile(String prefix, String suffix, File directory) throws IOException
    在指定目录中创建一个新的空文件,使用给定的前缀和后缀字符串生成其名称。
  • boolean renameTo(File dest):将文件或目录重命名为给定的目标路径。此方法比较常用。
    如果重命名操作成功,则返回 true;如果操作失败,则返回 false。
    这个方法可以用于移动文件或目录,只需将目标路径设置为不同的目录即可,但目录必须已存在。

请看文件创建和重命名操作的例程:

package file;
import java.io.File;
public class FileOperation {

public static void main(String[] args) throws Exception {
/***创建新文件***/
// 设置要创建的文件的路径
String filePath = "D:/temp/testM.txt";
// 创建File类
File fileToCreate  = new File(filePath);
// 创建新文件
    boolean isCreated = fileToCreate.createNewFile();
    if (isCreated) {
        System.out.println("文件已成功创建: " + filePath);
    } else {
        System.out.println("文件已存在: " + filePath);
    }

/***创建一个临时文件***/
    File tmpFile = File.createTempFile("tmpTest", "txt");
    System.out.println("临时文件创建成功: " + tmpFile.toString());

/***文件重命名或移动,若文件路径不同则为移动***/
// 设置要重命名的文件或目录的路径
String oldPath = "D:/src/file.txt";
// 设置新的文件或目录的路径
String newPath = "D:/src/tmp/newFile.txt";

// 创建File对象
File oldFile = new File(oldPath);
File newFile = new File(newPath);

// 尝试重命名文件或目录
boolean isRenamed = oldFile.renameTo(newFile);

if (isRenamed) {
    System.out.println("文件/目录已成功重命名: " + oldPath + " -> " + newPath);
} else {
    System.out.println("重命名文件/目录失败");
}
}

}

(二)、文件目录操作的方法:

  • String[] list():列出目录下所有子文件和子目录的名称。
  • String[] list(FilenameFilter filter) 用于过滤文件列表。‌ 这个方法允许你指定一个过滤器,只有满足该过滤器的目录文件才会被列出。这个方法返回一个此抽象路径名所表示目录中的文件和目录的字符串数组,包含所有满足过滤条件的文件目录名。
  • File[] listFiles():列出目录下所有子文件和子目录的 File 对象。
  • File[] listFiles(FileFilter filter) 返回表示此抽象路径名所表示目录中的文件和目录的抽象路径名数组,这些路径名满足特定过滤器。
  • boolean mkdir():创建一个新的空目录。如果该目录已经存在,此方法将不会做任何事情。
  • boolean mkdirs():创建多级目录(如果父目录不存在,会一并创建)。
  • boolean delete():删除文件或空目录。
  • boolean deleteOnExit():在Java虚拟机(JVM)退出时,自动删除此抽象路径名表示的文件。这个方法常用于临时文件的处理,确保即使在程序异常终止或忘记手动删除的情况下,临时文件也能被自动清除。

‌Java的File类中的String[] list(FilenameFilter filter)方法主要用于过滤文件列表。‌ 这个方法允许你指定一个过滤器,只有满足该过滤器的文件才会被列出。
以下是一个过滤显示目录文件例程FilterListDir:

package file;

import java.io.File;
import java.io.FilenameFilter;
public class FilterListDir { /*过滤列出指定目录*/

public static void main(String[] args) {
        File file = new File("D:/temp");
        FilenameFilter filter = new MyFilenameFilter("src");
        String[] paths = file.list(filter);
        for (String path : paths) {
            System.out.println(path);
        }
}
}

class MyFilenameFilter implements FilenameFilter {
    String strFilter;
    public MyFilenameFilter(String filterStr) {
    strFilter = filterStr;
    }
    @Override
    public boolean accept(File dir, String name) {
        return name.contains(strFilter); //包含strFilter
    }
}

例程的运行结果列出了指定目录中符合过滤条件的目录和文件名称,如下所示
在这里插入图片描述
文件目录操作(列出、创建、删除)的演示例程:

package file;
import java.io.File;
import java.util.Arrays;
public class FileDirOperation {
public static void listDir() { /*列出指定目录*/
String path = "D:/temp/";// 指定文件路径
// 创建File对象
File file = new File(path);

/***String[] list()列出指定目录下 子文件名和子目录的名称***/
String[] list = file.list();
// 数组转字符串并输出
System.out.println(Arrays.toString(list));

/**File[] listFiles():列出目录下所有子文件和子目录的 File对象***/
File[] filesList = file.listFiles();
// 遍历File对象数组,获取每个子对象
for (File file1 : filesList) System.out.println(file1);
}

public static void mkDir() {/*** 创建目录 ***/
/*** mkdir()创建目录 ***/
String newPath = "D:/temp/tmp";// 指定文件路径
// 创建File对象
File file = new File(newPath);
boolean is_mkdir = file.mkdir();
if (is_mkdir) {
    System.out.println(newPath + "目录创建成功!");
} else {
    System.out.println(newPath + "目录创建失败!");
}
    
// 要创建的新目录名
newPath = "D:/temp/src/tmp";
// 创建File对象
file = new File(newPath);
// 创建目录
is_mkdir = file.mkdirs();
if (is_mkdir) {
    System.out.println(newPath + "多级目录创建成功!");
} else {
    System.out.println(newPath + "多级目录创建失败!");
}
}

public static void delDir() {/*** 删除目录 ***/
/*** delete()删除目录 ***/
String deletePath = "D:/temp/tmp";// 指定删除的目录
// 创建 File 类
File file = new File(deletePath);
// 执行删除
boolean isDelete = file.delete();
if (isDelete){
    System.out.println("删除成功!");
}else {
    System.out.println("删除失败!");
}

/*** deleteOnExit()删除目录 ***/
// 要删除的目录
deletePath = "D:/temp/src/tmp";
// 创建一个 File 类
file = new File(deletePath);
// 执行注册删除(没有返回值)
file.deleteOnExit();
}

public static void main(String[] args) throws Exception {
listDir(); //列出目录信息
mkDir();  //创建目录
delDir();  //删除目录
}
}

我们再来看一个递归显示目录的例程。
一个递归打印目录树的例程PrintDirTree.java:
遍历输出指定目录的目录树详细信息,本例采用listFiles()的方法。亦可用list()方法实现,两方法用法相似,但返回值有差异。
有兴趣的读者可用list()方法改写试试。

package file;
/***
 * @author QiuGen
 * @description  遍历输出目录树PrintDirTree
 * @date 2024/10/11
 * ***/
import java.io.File;
import java.util.Date;
/***遍历输出目录树详细信息***/
public class PrintDirTree {

public static void main(String[] args) {
String path = "D:/src"; //指定一个目录
printDirTree( new File(path) );
}

public static  void printDirTree(File file){
        System.out.println(file.getName() + "目录树详细信息:");
        int level = 0;
        printDirTree(file,level);
}

public static  void printDirTree(File file, int level){
        System.out.print("|-");
        for (int i = 0; i < level; i++) System.out.printf("--");
        if (file.isDirectory()){
            System.out.println(getFileDetails(file));
            File [] files = file.listFiles();
            for (File tmp: files) printDirTree(tmp, level+1);
        } else  printFileDetails(file);
}

public static  void printFileDetails(File file){
System.out.println(getFileDetails(file));
}

    private static String getFileDetails(File file) {
        String details = "";
        details=details+file.getName()+"\t"+(file.isDirectory()?"目录":"文件") +"\t";
        if (file.isDirectory())
        details += "---\t";
        else details += file.length() + "字节\t";

        details += new Date(file.lastModified());
        return details;
    }   
}

我实际的src目录显示图:
在这里插入图片描述

我的”打印目录树“例程测试效果图:
在这里插入图片描述

(三)、文件目录相关属性查询的方法:
1,路径属性查询方法:

  • public String getAbsolutePath():获取文件或目录的绝对路径。
  • public String getPath():获取文件或目录的路径。
  • public String getName():获取文件或目录的名称。
  • public String getParent():获取文件或目录的父路径。
  • public File getParentFile():获取文件或目录的父 File 对象。
  • public boolean isAbsolute():判断路径是否为绝对路径。
  • public File getCanonicalFile():返回此 File 对象的规范路径名形式,处理符号链接等特殊情况。

2,文件属性查询方法

  • public boolean canRead()测试应用程序是否可以读取此抽象路径名表示的文件。
  • public boolean canWrite()测试应用程序是否可以修改此抽象路径名表示的文件。
  • public boolean exists():判断文件或目录是否存在。
  • public boolean isDirectory():判断是否为目录。
  • public boolean isFile():判断是否为普通文件。
  • public long length():获取文件的长度(字节数)。
  • public long lastModified():获取最后一次修改时间(毫秒值)。

文件目录属性查询的演示例程FileDirAttributeQuery:

package file;
import java.io.File;
import java.io.IOException;
public class FileDirAttributeQuery {
public static void queryDirAttribute() throws IOException {
// 使用相对路径创建File对象
File file = new File("tmp/src/test.dat");
// 获取文件或目录的绝对路径
System.out.println("绝对路径: " + file.getAbsolutePath());
// 获取文件或目录的路径。
System.out.println("路径: " + file.getPath());
// 获取文件或目录的名称。
System.out.println("文件名: " + file.getName());
// 获取文件或目录的父路径。
System.out.println("父路径: " + file.getParent());
// 获取文件或目录的父File对象
System.out.println("父File对象: " + file.getParentFile());
// 判断路径是否为绝对路径。
System.out.println("是否为绝对路径? " + file.isAbsolute());
// 返回此 File 对象的规范路径名形式
System.out.println("规范路径名: "+ file.getCanonicalFile()); // 会有IO异常
}

public static void queryFileAttribute() {
// 文件路径
String filePath = "D:/Temp/music/大约在冬季.mp3";
// 使用相对路径创建File对象
File file = new File(filePath);

// 判断文件或目录是否存在
System.out.println("文件是否存在? " + file.exists());
// 判断是否为目录
System.out.println("判断是否为目录? " + file.isDirectory());
// 判断是否为普通文件
System.out.println("判断是否为普通文件? " + file.isFile());
if (file.isFile()) {
    // 获取文件的长度(字节数)
    System.out.println("文件长度: " + file.length() + " 字节");
    // 获取最后一次修改时间(毫秒值)
    System.out.println("最后修改时间: " + file.lastModified());
}
}

public static void main(String[] args) throws Exception {
queryDirAttribute();
//queryFileAttribute();
}
}

例程测试演示结果:
在这里插入图片描述

(四)、文件目录的其他操作方法:

  • public boolean setLastModified(long time)设置由此抽象路径名所指定的文件或目录的最后一次修改时间。
  • public boolean setReadOnly() 设置此抽象路径名指定的文件或目录,以便只可对其进行读操作。
  • public int compareTo(File pathname) 按字母顺序比较两个抽象路径名。
  • public int compareTo(Object o) 按字母顺序比较抽象路径名与给定对象。
  • public boolean equals(Object obj) 测试此抽象路径名与给定对象是否相等。
  • public String toString() 返回此抽象路径名的路径名字符串。

说明:
File 类只能操作文件和目录的元数据(如名称、路径、属性),不能用于文件内容的读写。文件内容的读写需要借助输入/输出流(如 FileInputStream、FileOutputStream)实现。
File 类是独立于操作系统平台的。
File 类的设计早于Java NIO(New I/O),后者提供了更高级的文件I/O操作,效率也更高。

四、文件统计程序FilesStatistics
在博文的最后,再分享一个统计目录中各种类型文件数的实用程序FilesStatistics:

package file;
/***
 * @author QiuGen
 * @description  按文件扩展名统计目录中的文件FilesStatistics
 * 说明:按文件扩展名统计目录中的文件,包括子目录中的文件。
 * @date 2024/10/12
 * ***/
import java.io.File;
import java.util.HashMap;
public class FilesStatistics {
// 创建HashMap保存统计信息,key用于保存后缀名 value用于保存统计数
static HashMap<String, Integer> countMap = new HashMap<>();

public static void main(String[] args) {
//指定统计的目标文件夹的File对象
File file = new File("D:/src");
statisticsFile(file);//调用统计方法
countMap.forEach((k,v)->System.out.println(k + "类型的文件有" + v + "个"));
}

// 统计目录中的文件数的方法
public static void statisticsFile(File path) {
File files[] = path.listFiles();

for (File file : files) { //遍历File[]
if (file.isFile()) { //是文件
countFile(file); //递归方法的终止点:文件计数
} else { //是目录
statisticsFile(file);//是文件夹,递归
}
}
}
//文件计数的方法。这是递归终结点
public static void countFile(File path) {
//获取文件名
String fileName = path.getName();
//根据尾部的.截取字符串。分割为文件名和扩展名两部分
String strs[] = fileName.split("\\.");
String key = strs[1];//strs[strs.length - 1];的优化写法
/***这是老式写法,这里可用一行代替***/
 if ( countMap.containsKey(key) ) { //Map包含有此key
 Integer value = countMap.get(key);
 //在此value值的基础上+1
 countMap.put(key, value + 1);
} else { //Map不包含此key,添加此key
countMap.put(key, 1);
}
}
}

程序FilesStatistics说明:
重点说明一下,它的递归终结点方法,也就是countFile(File path)方法,为了让初学者便于理解,这里使用了一种传统的老式写法,请看代码:

//文件计数的方法。这是递归终结点
public static void countFile(File path) {
//获取文件名
String fileName = path.getName();
//根据尾部的.截取字符串。分割为文件名和扩展名两部分
String strs[] = fileName.split("\\.");
String key = strs[1];//strs[strs.length - 1];的优化写法
/***这是老式写法,这里可用一行代替***/
 if ( countMap.containsKey(key) ) { //Map包含有此key
 Integer value = countMap.get(key);
 //在此value值的基础上+1
 countMap.put(key, value + 1);
} else { //Map不包含此key,添加此key
countMap.put(key, 1);
}
}

实际上,上面这个方法的最后if…else分枝语句块可用一行代码替换,但是初学者理解起来会有难度。
这里给一个提示,读者可自行去探索。一旦学会,以后碰到类似场景就会想到这个用法了。
借助Map的getOrDefault()方法,就可一行搞定if…else分枝语句块的业务逻辑。

参考文献资料:


原文地址:https://blog.csdn.net/weixin_42369079/article/details/142824292

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!