1. 概述
本文将系统性地介绍 Java 中的 File
类,它是 java.io
包的重要组成部分。✅ File
类的核心作用是让我们能够操作文件系统中的文件和目录,比如创建、删除、重命名、获取元数据等。
⚠️ 但必须强调一点:**File
类本身不能读写文件内容**。它只负责文件/目录的“元操作”,真正的读写需要配合 InputStream
/ OutputStream
等 IO 流来完成。
2. 创建 File 对象
File
类提供了 4 个公共构造函数,开发者可以根据不同场景选择使用:
File(String pathname)
直接通过路径字符串创建 File 实例。File(String parent, String child)
通过父路径和子路径拼接创建,避免手动拼接路径分隔符。File(File parent, String child)
父路径用另一个File
对象表示,适合链式操作。File(URI uri)
通过 URI 创建,适用于更复杂的资源定位场景。
✅ 推荐使用
File.separator
而不是硬编码/
或\
,保证跨平台兼容性。
3. File 类常用操作
3.1 创建与删除文件/目录
File
提供了简单粗暴的创建和删除方法:
- ✅ 创建目录:
mkdir()
或mkdirs()
(递归创建) - ✅ 创建文件:
createNewFile()
- ✅ 删除:
delete()
所有方法返回 boolean
,成功为 true
,失败为 false
(比如文件不存在或权限不足)。
@Test
public void givenDir_whenMkdir_thenDirIsDeleted() {
File directory = new File("dir");
assertTrue(directory.mkdir());
assertTrue(directory.delete());
}
@Test
public void givenFile_whenCreateNewFile_thenFileIsDeleted() {
File file = new File("file.txt");
try {
assertTrue(file.createNewFile());
} catch (IOException e) {
fail("Could not create file.txt");
}
assertTrue(file.delete());
}
常用判断方法
exists()
:文件或目录是否存在isDirectory()
:是否是目录isFile()
:是否是文件
这些方法在操作前做预检非常有用,避免踩坑 ❌。
3.2 获取文件元数据
File
类提供了一些方法来获取路径和结构信息:
getName()
:获取文件名(不含路径)getParentFile()
:返回父目录的File
对象getPath()
:返回构造时传入的路径字符串
示例代码:
@Test
public void givenFile_whenCreateNewFile_thenMetadataIsCorrect() {
String sep = File.separator;
File parentDir = makeDir("filesDir");
File child = new File(parentDir, "file.txt");
try {
child.createNewFile();
} catch (IOException e) {
fail("Could not create file.txt");
}
assertEquals("file.txt", child.getName());
assertEquals(parentDir.getName(), child.getParentFile().getName());
assertEquals(parentDir.getPath() + sep + "file.txt", child.getPath());
removeDir(parentDir);
}
⚠️ 注意
getPath()
返回的是构造路径,不一定是绝对路径。如需绝对路径,使用getAbsolutePath()
。
3.3 设置文件权限
File
类支持简单的权限控制,适用于一些基础场景:
setWritable(boolean)
:设置是否可写setReadable(boolean)
:设置是否可读
一旦设置为不可写/读,再进行对应操作会抛出 IOException
。
示例:禁止写入
@Test
public void givenReadOnlyFile_whenCreateNewFile_thenCantModFile() {
File parentDir = makeDir("readDir");
File child = new File(parentDir, "file.txt");
try {
child.createNewFile();
} catch (IOException e) {
fail("Could not create file.txt");
}
child.setWritable(false);
boolean writable = true;
try (FileOutputStream fos = new FileOutputStream(child)) {
fos.write("Hello World".getBytes());
fos.flush();
} catch (IOException e) {
writable = false;
} finally {
removeDir(parentDir);
}
assertFalse(writable);
}
示例:禁止读取
@Test
public void givenWriteOnlyFile_whenCreateNewFile_thenCantReadFile() {
File parentDir = makeDir("writeDir");
File child = new File(parentDir, "file.txt");
try {
child.createNewFile();
} catch (IOException e) {
fail("Could not create file.txt");
}
child.setReadable(false);
boolean readable = true;
try (FileInputStream fis = new FileInputStream(child)) {
fis.read();
} catch (IOException e) {
readable = false;
} finally {
removeDir(parentDir);
}
assertFalse(readable);
}
⚠️ 这些权限控制在某些操作系统(如 Windows)上可能不生效,建议在关键场景使用更严格的权限管理机制。
3.4 列出目录中的文件
File
提供了两个常用方法来列出目录内容:
list()
:返回文件名字符串数组list(FilenameFilter)
:支持过滤,只返回符合条件的文件名
示例:过滤 .csv
文件
@Test
public void givenFilesInDir_whenCreateNewFile_thenCanListFiles() {
File parentDir = makeDir("filtersDir");
String[] files = {"file1.csv", "file2.txt"};
for (String file : files) {
try {
new File(parentDir, file).createNewFile();
} catch (IOException e) {
fail("Could not create " + file);
}
}
// 正常列出
assertEquals(2, parentDir.list().length);
// 过滤列出
FilenameFilter csvFilter = (dir, ext) -> ext.endsWith(".csv");
assertEquals(1, parentDir.list(csvFilter).length);
removeDir(parentDir);
}
✅
FilenameFilter
是函数式接口,可以直接用 Lambda 表达式实现,简洁明了。
3.5 重命名文件或目录
使用 renameTo(File dest)
方法可以重命名或移动文件/目录。
@Test
public void givenDir_whenMkdir_thenCanRenameDir() {
File source = makeDir("source");
File destination = makeDir("destination");
boolean renamed = source.renameTo(destination);
if (renamed) {
assertFalse(source.isDirectory());
assertTrue(destination.isDirectory());
removeDir(destination);
}
}
⚠️ 注意:
renameTo
返回boolean
,失败可能因为目标已存在、权限不足或跨文件系统(某些平台不支持跨分区重命名)。- 如果目标文件已存在,行为是平台相关的,通常会失败。
3.6 获取磁盘空间信息
File
类还能获取磁盘使用情况,适用于监控或容量预判:
getTotalSpace()
:总空间getFreeSpace()
:剩余空间getUsableSpace()
:用户可用空间(考虑配额)
示例:验证写入后剩余空间减少
@Test
public void givenDataWritten_whenWrite_thenFreeSpaceReduces() {
String home = System.getProperty("user.home");
String sep = File.separator;
File testDir = makeDir(home + sep + "test");
File sample = new File(testDir, "sample.txt");
long freeSpaceBefore = testDir.getFreeSpace();
try {
writeSampleDataToFile(sample);
} catch (IOException e) {
fail("Could not write to sample.txt");
}
long freeSpaceAfter = testDir.getFreeSpace();
assertTrue(freeSpaceAfter < freeSpaceBefore);
removeDir(testDir);
}
✅ 这些方法对根目录或挂载点调用最有效,比如
new File("/")
或new File("C:\\")
。
4. 总结
File
类虽然简单,但在传统 IO 操作中仍是不可或缺的基础工具。它提供了对文件系统的基本操作能力,包括:
- ✅ 文件/目录的创建、删除、重命名
- ✅ 元数据获取与权限设置
- ✅ 目录遍历与磁盘空间查询
⚠️ 但也要注意它的局限性:
- 无法读写文件内容
- 某些方法行为依赖操作系统
- 异常处理必须严谨(尤其是
IOException
)
📌 补充建议:在 Java 7+ 环境中,推荐优先使用
java.nio.file.Path
和Files
工具类,它们提供了更强大、更安全的文件操作 API。
所有示例代码已托管至 GitHub:https://github.com/baeldung/core-java-modules/tree/master/core-java-io-apis