源本科技 | 码上会

Java File

2026/01/30
48
0

学习目标

  • 理解 File 类的核心作用与设计定位

  • 掌握 File 对象的创建方式与常用构造器

  • 熟练使用 File 类查询文件 / 目录属性(存在性、权限、大小等)

  • 能够遍历目录内容并区分文件与子目录

  • 了解路径分隔符等系统相关字段的用途


什么是 File 类

java.io.File 类是 Java 中用于表示文件或目录路径名的抽象类。它提供了一种与平台无关的方式来操作文件系统,但不涉及文件内容的读写——那是 I/O 流(如 FileReaderFileInputStream)的职责。

核心特点

  • 抽象表示File 对象仅封装路径信息,不保证对应实体存在

  • 不可变性:一旦创建,其路径名不能更改

  • 平台无关:自动处理不同操作系统的路径格式

  • 元数据操作:支持查询和修改文件属性(权限、时间戳等)

简单说:File 告诉你“在哪里”,流(Stream)负责“读写什么


创建 File 对象

File 类提供四种构造器,适应不同路径组合需求:

构造器

说明

示例

File(String pathname)

从完整路径字符串创建

new File("docs/report.txt")

File(String parent, String child)

从父路径 + 子路径创建

new File("docs", "report.txt")

File(File parent, String child)

从父 File 对象 + 子路径创建

new File(parentDir, "data.log")

File(URI uri)

file:// URI 创建

new File(Paths.get("data.txt").toUri())

// 示例:多种创建方式
File file1 = new File("config/app.properties");
File file2 = new File("config", "app.properties");
File configDir = new File("config");
File file3 = new File(configDir, "app.properties");

// 三者等价(在相同工作目录下)

路径分隔符

File 类提供静态字段,帮助编写跨平台路径代码:

字段

类型

说明

示例值

separator

String

文件名分隔符

Linux: "/", Windows: "\"

separatorChar

char

同上,字符形式

'/''\'

pathSeparator

String

路径列表分隔符(如 PATH 环境变量)

Linux: ":", Windows: ";"

pathSeparatorChar

char

同上,字符形式

':'';'

// 跨平台安全的路径拼接(不推荐,应使用 Paths.get())
String path = "home" + File.separator + "user" + File.separator + "data.txt";

// 更佳实践(Java 7+):
Path path = Paths.get("home", "user", "data.txt");

核心方法

1. 路径信息查询

方法

返回值

说明

getName()

String

返回文件 / 目录名(不含路径)

getPath()

String

返回构造时传入的原始路径

getAbsolutePath()

String

返回绝对路径(基于当前工作目录解析)

getCanonicalPath()

String

返回规范路径(解析 ...,消除符号链接)

getParent()

String

返回父目录路径字符串

getParentFile()

File

返回父目录的 File 对象

File file = new File("../logs/app.log");
System.out.println("Name: " + file.getName());           // app.log
System.out.println("Path: " + file.getPath());           // ../logs/app.log
System.out.println("Absolute: " + file.getAbsolutePath()); // /current/working/dir/../logs/app.log
System.out.println("Canonical: " + file.getCanonicalPath()); // /actual/path/to/logs/app.log

2. 文件存在与类型

方法

说明

exists()

文件 / 目录是否存在

isFile()

是否为普通文件(且存在)

isDirectory()

是否为目录(且存在)

isHidden()

是否为隐藏文件(平台相关)

3. 权限检查

方法

说明

canRead()

当前用户是否有读权限

canWrite()

当前用户是否有写权限

canExecute()

当前用户是否有执行权限

4. 文件属性

方法

返回值

说明

length()

long

文件大小(字节),目录返回 0

lastModified()

long

最后修改时间(毫秒,自 Unix epoch)

getFreeSpace()

long

所在分区的可用空间(字节)

5. 文件操作

方法

说明

createNewFile()

原子性创建新空文件(若不存在)

delete()

删除文件或空目录

mkdir()

创建单级目录

mkdirs()

创建多级目录(包括必要父目录)

renameTo(File dest)

重命名或移动文件(已过时,推荐 Files.move()

6. 目录内容遍历

方法

返回值

说明

list()

String[]

返回目录中所有条目的名称数组

listFiles()

File[]

返回目录中所有条目的File 对象数组

listFiles(FileFilter)

File[]

FileFilter 过滤结果

listFiles(FilenameFilter)

File[]

按文件名过滤结果


实战示例

文件详细信息

import java.io.File;
import java.util.Date;

public class FileInfo {
    public static void main(String[] args) {
        if (args.length == 0) {
            System.err.println("请提供文件路径作为参数");
            return;
        }

        File file = new File(args[0]);
        
        System.out.println("=== 文件信息 ===");
        System.out.println("名称: " + file.getName());
        System.out.println("路径: " + file.getPath());
        System.out.println("绝对路径: " + file.getAbsolutePath());
        System.out.println("父目录: " + file.getParent());
        System.out.println("是否存在: " + file.exists());

        if (file.exists()) {
            System.out.println("是否为文件: " + file.isFile());
            System.out.println("是否为目录: " + file.isDirectory());
            System.out.println("是否可读: " + file.canRead());
            System.out.println("是否可写: " + file.canWrite());
            System.out.println("文件大小: " + file.length() + " 字节");
            System.out.println("最后修改: " + new Date(file.lastModified()));
        }
    }
}

运行示例:

java FileInfo notes.txt

遍历目录内容

import java.io.File;
import java.io.IOException;
import java.util.Scanner;

public class DirectoryLister {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        
        System.out.print("请输入目录路径: ");
        String dirPath = scanner.nextLine();
        
        File dir = new File(dirPath);
        
        if (!dir.exists()) {
            System.out.println("目录不存在");
            return;
        }
        
        if (!dir.isDirectory()) {
            System.out.println("路径不是目录");
            return;
        }
        
        System.out.println("\n=== 目录内容 ===");
        File[] entries = dir.listFiles();
        if (entries != null) {
            for (File entry : entries) {
                String type = entry.isDirectory() ? "【目录】" : "📄 文件";
                System.out.printf("%s %s (%d 字节)\n", 
                    type, entry.getName(), entry.length());
            }
            System.out.println("\n总计: " + entries.length + " 项");
        } else {
            System.out.println("无法读取目录内容(可能无权限)");
        }
    }
}

使用 listFiles()list() 更强大,因为可直接调用 isFile()/isDirectory()


高级技巧

创建临时文件

try {
    File tempFile = File.createTempFile("temp_", ".txt");
    System.out.println("临时文件: " + tempFile.getAbsolutePath());
    
    // 程序退出时自动删除
    tempFile.deleteOnExit();
} catch (IOException e) {
    e.printStackTrace();
}

过滤特定文件

// 只列出 .txt 文件
File dir = new File("documents");
File[] textFiles = dir.listFiles((dir1, name) -> name.endsWith(".txt"));

if (textFiles != null) {
    for (File file : textFiles) {
        System.out.println("文本文件: " + file.getName());
    }
}

规范化路径(消除 .. 和 .)

File file = new File("a/b/../c/./data.txt");
System.out.println("原始路径: " + file.getPath());         // a/b/../c/./data.txt
System.out.println("规范路径: " + file.getCanonicalPath()); // /absolute/path/to/a/c/data.txt

最佳实践

  1. File 不等于实际文件:创建 File 对象不会在磁盘生成文件

  2. 路径分隔符:避免硬编码 /\,使用 File.separatorPaths.get()

  3. renameTo() 已过时:Java 7+ 应使用 Files.move(source, target)

  4. 目录删除限制delete() 无法删除非空目录,需递归删除内容

  5. 异常处理getCanonicalPath() 可能抛出 IOException

  6. 现代替代方案:Java 7 引入的 java.nio.file 包(PathFiles)功能更强大,推荐新项目使用


重点总结

  • File 类是文件 / 目录的路径抽象,不处理内容读写

  • 提供四大构造器,灵活组合父路径与子路径

  • 核心能力:属性查询存在性检查目录遍历基础文件操作

  • 关键方法:exists()isFile()listFiles()createNewFile()delete()

  • 路径分隔符字段(separator)助力跨平台开发

  • 对于复杂文件操作,建议迁移到 java.nio.file API


思考题

  1. getAbsolutePath()getCanonicalPath() 在什么情况下会返回不同结果?请举例说明。

  2. 为什么 File.delete() 无法删除非空目录?如何实现递归删除整个目录树?

  3. 在现代 Java 开发中,java.io.Filejava.nio.file.Path 各有什么优势?何时应优先选择后者?