Java File类新手入门全解
目录
3.2 File(String parent, String child)
3.3 File(File parent, String child)
这是一份为您精心准备的Java File类学习指南。不仅仅是一份代码,更是一堂完整的入门课程。
我们将分为两个部分:
-
Java代码文件 (
FileLearningDemo.java):包含一个完整的、可运行的示例程序。我不只是写了代码,我把“教科书”写进了注释里。每一行代码,包括import,都有详细的“保姆级”解说。 -
详细教程文档 (
JavaFileClassGuide.md):这是一份超过4000字的深度解析,涵盖了您提供的图片中的所有知识点,扩展了底层原理、常见坑点、面试题以及现代Java (NIO) 的对比。
我们先从代码开始,请仔细阅读代码中的注释,它们是为您专门定制的。
/**
* ==============================================================================================
* JAVA FILE 类新手入门全解
* ==============================================================================================
* * 【写在前面 - 给新手小白的话】
* 欢迎来到 Java IO (Input/Output) 的世界!
* 在 Java 中,我们想要操作电脑硬盘上的文件(比如创建一个文本文档、新建一个文件夹、删除一个图片),
* 我们首先需要一个“代理人”或者“抓手”,这个抓手就是 `java.io.File` 类。
* * 核心概念误区扫盲:
* 1. File 类对象代表什么?
* 它代表文件系统中的一个【路径名】(Pathname)。
* 注意:它 *不* 代表文件里的具体内容(数据)。File 对象就像是文件的“户口本”或“地址牌”,
* 你可以通过它知道文件在哪、叫什么、多大、是否存在,但不能直接通过它往文件里写字(写字需要用 Stream 流)。
* * 2. new File("...") 会在硬盘创建文件吗?
* 不会!这只是在内存里创建了一个 Java 对象。
* 只有当你调用 .createNewFile() 或 .mkdir() 等方法时,才会真正跟硬盘交互。
* * ==============================================================================================
*/
// 导入必要的包
// java.io 是 Java 的标准输入输出包,File 类就住在这里。
import java.io.File;
// IOException 是“输入输出异常”。操作文件是很危险的(文件可能被占用、磁盘可能满了、没有权限等),
// 所以 Java 强制要求我们必须处理这些潜在的错误。
import java.io.IOException;
// Date 类用于处理时间,比如查看文件的最后修改时间。
import java.util.Date;
// SimpleDateFormat 用于把机器看的时间(毫秒数)转换成我们人能看懂的格式(比如 "2023-10-27 10:00:00")。
import java.text.SimpleDateFormat;
/**
* 主演示类
*/
public class FileLearningDemo {
/**
* main 方法:程序的入口,就像大楼的大门。
* public: 公共的,谁都能访问。
* static: 静态的,不需要实例化对象就能运行。
* void: 没有返回值。
* String[] args: 接收命令行参数。
*/
public static void main(String[] args) {
System.out.println("========== 开始 Java File 类学习演示 ==========\n");
// -----------------------------------------------------------------------
// 第一部分:了解分隔符(扩展知识点:跨平台性)
// -----------------------------------------------------------------------
System.out.println("--- 1. 跨平台的分隔符知识 ---");
// Windows 系统中,路径通常用反斜杠 "\" (例如 C:\Users\Admin)
// Linux/Mac 系统中,路径通常用正斜杠 "/" (例如 /home/user)
// 如果我们在代码里写死 "\",代码放到 Linux 服务器上就会报错。
// 为了解决这个问题,Java 提供了 File.separator,它会根据操作系统自动变化。
String separator = File.separator;
System.out.println("当前系统的名称分隔符 (File.separator): " + separator);
// pathSeparator 是路径分隔符,Windows是分号";",Linux是冒号":" (主要用于环境变量)
System.out.println("当前系统的路径分隔符 (File.pathSeparator): " + File.pathSeparator);
System.out.println("【小白提示】写代码时,尽量用 File.separator 拼接路径,不要手写 / 或 \\,这样代码更专业、兼容性更好。\n");
// -----------------------------------------------------------------------
// 第二部分:构造方法 - 创建 File 对象的三种姿势
// -----------------------------------------------------------------------
System.out.println("--- 2. 构造 File 对象 ---");
// 设定一个基础目录,为了演示方便,我们在当前项目目录下创建一个 "demo_dir"
// "." 代表当前 Java 项目的根目录
String projectRoot = ".";
// 【姿势 1】:File(String pathname) - 最常用的方式
// 直接传入完整的路径字符串
File rootDir = new File(projectRoot + File.separator + "demo_dir");
System.out.println("准备创建的根目录对象: " + rootDir);
// 【姿势 2】:File(File parent, String child) - 父子分离法
// 这里的 parent 是一个 File 对象,child 是字符串文件名
// 场景:你已经有了一个目录对象,想在这个目录下找个文件
File subDir = new File(rootDir, "images");
System.out.println("准备创建的子目录对象(images): " + subDir);
// 【姿势 3】:File(String parent, String child) - 字符串拼接法
// parent 是字符串路径,child 是字符串文件名
// 场景:只知道两个路径字符串,想拼在一起
File targetFile = new File(projectRoot + File.separator + "demo_dir" + File.separator + "images", "test_image.txt");
System.out.println("准备操作的目标文件对象: " + targetFile);
System.out.println("注意:此时硬盘上还什么都没有,上面只是在内存里造了对象!\n");
// -----------------------------------------------------------------------
// 第三部分:创建与删除 (mkdir, mkdirs, createNewFile)
// -----------------------------------------------------------------------
System.out.println("--- 3. 实际操控硬盘:创建与删除 ---");
// 1. 创建目录
// mkdir(): make directory。只能创建一级目录。如果父目录不存在,它会失败。
// mkdirs(): make directories。能够创建多级目录。如果父目录不存在,它会一并帮你创建。推荐使用这个!
// 判断目录是否存在
if (!rootDir.exists()) {
// 尝试创建 demo_dir
boolean dirCreated = rootDir.mkdirs();
System.out.println("创建根目录 " + rootDir.getName() + " 结果: " + dirCreated);
} else {
System.out.println("根目录 " + rootDir.getName() + " 已经存在,无需创建。");
}
// 尝试创建子目录 demo_dir/images
if (!subDir.exists()) {
boolean subDirCreated = subDir.mkdirs();
System.out.println("创建子目录 " + subDir.getName() + " 结果: " + subDirCreated);
}
// 2. 创建文件
// createNewFile() 会抛出 IOException,必须处理!
// 为什么?因为硬盘可能坏了,或者没有权限写入,这些都是 Java 无法控制的意外。
try {
if (!targetFile.exists()) {
// 当且仅当文件不存在时,创建一个新的空文件
boolean fileCreated = targetFile.createNewFile();
System.out.println("创建文件 " + targetFile.getName() + " 结果: " + fileCreated);
} else {
System.out.println("文件 " + targetFile.getName() + " 已经存在。");
}
} catch (IOException e) {
// 这是一个标准的异常处理块
System.err.println("发生错误了!无法创建文件。");
e.printStackTrace(); // 打印错误堆栈,方便程序员找bug
}
System.out.println();
// -----------------------------------------------------------------------
// 第四部分:获取文件信息 (Get系列方法)
// -----------------------------------------------------------------------
System.out.println("--- 4. 获取文件信息 (Get方法演示) ---");
// 获取文件名
System.out.println("getName() 文件名: " + targetFile.getName());
// 获取父目录路径 (返回字符串)
System.out.println("getParent() 父目录路径: " + targetFile.getParent());
// 获取路径 (构造时怎么写,这里就返回什么)
System.out.println("getPath() 构造路径: " + targetFile.getPath());
// 获取绝对路径 (从盘符开始的完整路径,如 C:\Code\...\test.txt)
System.out.println("getAbsolutePath() 绝对路径: " + targetFile.getAbsolutePath());
// 获取规范路径 (Canonical Path) - 这是一个高级扩展点
// 它会解析路径中的 ".." (上一级) 和 "." (当前级),消除冗余。
try {
System.out.println("getCanonicalPath() 规范路径: " + targetFile.getCanonicalPath());
} catch (IOException e) {
e.printStackTrace();
}
// 获取文件大小 (字节数)
System.out.println("length() 文件大小: " + targetFile.length() + " 字节");
// 获取最后修改时间
long lastModified = targetFile.lastModified(); // 返回的是毫秒数
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("lastModified() 最后修改时间: " + sdf.format(new Date(lastModified)));
System.out.println();
// -----------------------------------------------------------------------
// 第五部分:判断功能 (is系列方法)
// -----------------------------------------------------------------------
System.out.println("--- 5. 判断文件类型 ---");
System.out.println("exists() 是否存在? " + targetFile.exists());
// 即使文件存在,我们也要区分它是“文件夹”还是“文件”
// 注意:isDirectory() 和 isFile() 互斥。
System.out.println("isDirectory() 是文件夹吗? " + targetFile.isDirectory());
System.out.println("isFile() 是普通文件吗? " + targetFile.isFile());
// 权限判断
System.out.println("canRead() 可读? " + targetFile.canRead());
System.out.println("canWrite() 可写? " + targetFile.canWrite());
System.out.println("isHidden() 是隐藏文件吗? " + targetFile.isHidden());
System.out.println();
// -----------------------------------------------------------------------
// 第六部分:重命名 (renameTo)
// -----------------------------------------------------------------------
System.out.println("--- 6. 重命名与移动 ---");
// renameTo 既可以改名,也可以移动文件(如果路径不同)
// 我们把 test_image.txt 改名为 ren_test.txt
File newNameFile = new File(subDir, "ren_test.txt");
if (targetFile.exists() && !newNameFile.exists()) {
// 只有源文件存在,且目标名字没被占用时,才重命名
boolean isRenamed = targetFile.renameTo(newNameFile);
System.out.println("重命名结果: " + isRenamed);
// 此时 targetFile 代表的路径已经没有文件了,newNameFile 代表的路径有文件
System.out.println("旧对象 targetFile 还能找到文件吗? " + targetFile.exists()); // 应为 false
System.out.println("新对象 newNameFile 存在吗? " + newNameFile.exists()); // 应为 true
// 为了后续演示删除,我们把引用指回来
targetFile = newNameFile;
} else {
System.out.println("重命名条件不满足(源文件不存在或目标文件已存在)");
}
System.out.println();
// -----------------------------------------------------------------------
// 第七部分:遍历目录 (list 与 listFiles)
// -----------------------------------------------------------------------
System.out.println("--- 7. 遍历目录 (List功能) ---");
// 我们再在 subDir 下多建几个假文件为了演示
try {
new File(subDir, "a.jpg").createNewFile();
new File(subDir, "b.png").createNewFile();
} catch (IOException e) {}
// list(): 返回字符串数组 (String[]),只有文件名,没有路径
System.out.println("=== list() 演示 ===");
String[] fileNames = subDir.list();
if (fileNames != null) {
for (String name : fileNames) {
System.out.println("找到文件名: " + name);
}
}
// listFiles(): 返回 File 对象数组 (File[]),包含完整信息。推荐使用!
System.out.println("\n=== listFiles() 演示 ===");
File[] files = subDir.listFiles();
if (files != null) {
for (File f : files) {
if (f.isFile()) {
System.out.println("[文件] " + f.getName() + " | 大小: " + f.length());
} else {
System.out.println("[目录] " + f.getName());
}
}
}
System.out.println();
// -----------------------------------------------------------------------
// 第八部分:清理战场 (Delete)
// -----------------------------------------------------------------------
System.out.println("--- 8. 删除演示 ---");
// delete() 删除文件或目录。
// 【重要知识点】:如果要删除一个目录,这个目录必须是空的!
// 如果目录里有文件,直接删除目录会失败。
System.out.println("尝试直接删除非空目录 " + subDir.getName() + ": " + subDir.delete()); // 应该返回 false
// 正确做法:先删除里面的文件,再删除目录
if (files != null) {
for (File f : files) {
boolean deleted = f.delete();
System.out.println("删除内部文件 " + f.getName() + ": " + deleted);
}
}
// 现在目录空了,可以删除了
System.out.println("再次尝试删除目录 " + subDir.getName() + ": " + subDir.delete()); // 应该返回 true
// 最后删除根目录
System.out.println("删除根目录 " + rootDir.getName() + ": " + rootDir.delete());
System.out.println("\n========== 演示结束 ==========");
// deleteOnExit() 演示
// 这是一个特殊的删除方法,它不会立即删除,而是等到 Java 虚拟机 (JVM) 停止运行时才删除。
// 常用在临时文件的处理上。
// File temp = new File("temp.log");
// temp.deleteOnExit();
}
}
打开
如何使用这些文件?
-
阅读文档:先通读
JavaFileClassGuide.md,理解每个概念。 -
运行代码:将
FileLearningDemo.java保存到你的电脑上,使用 IDE (如 IntelliJ IDEA 或 Eclipse) 打开运行,或者在命令行使用javac FileLearningDemo.java编译并运行。 -
观察输出:对照控制台的输出结果和代码中的注释,你将直观地看到每个方法的实际效果。
希望这份详细的解释能帮助你顺利通过 Java IO 的新手村!如果有任何疑问,欢迎随时提问。
Java File 类详解:新手小白的进阶之路
1. 前言:什么是 java.io.File?
对于新手来说,File 类是进入 Java IO(输入/输出)世界的第一道门。
在你的电脑桌面上,你看到的是一个个文件夹、文本文件、图片。在 Java 代码的世界里,这些东西都通过 File 类的对象来表示。
核心概念(划重点):
File对象是文件或目录路径名的抽象表示。
这意味着:
-
它只是一个路径:当你
new File("C:\\abc.txt")时,Java 只是在内存里记录了这个路径。如果硬盘上根本没有abc.txt,这个对象依然可以创建成功,不会报错。 -
它既可以是文件,也可以是文件夹:在 Java 中,文件和文件夹(目录)都用
File类表示,通过方法来区分。 -
它不操作内容:你不能用
File类去修改文件里的文字(比如把 "Hello" 改成 "World")。File类只管“外围”的事(改名、删除、判断大小、创建),读写内容需要用到InputStream或OutputStream。
2. 详解:File 类的核心属性与跨平台
(对应您提供的图1内容)
2.1 分隔符的烦恼
在 Windows 上,路径通常是 C:\Users\Admin(反斜杠 \)。
在 Linux/Mac 上,路径通常是 /home/admin(正斜杠 /)。
如果你在代码里写死了:
File f = new File("C:\\myproject\\data.txt"); // 错误示范!
这段代码放到 Linux 服务器上不仅找不到文件,还可能报错。
2.2 解决方案:File.separator
Java 提供了静态常量来解决这个问题:
-
static String separator: 与系统有关的默认名称分隔符。-
Windows 下是
\ -
Linux 下是
/
-
-
static String pathSeparator: 与系统有关的路径分隔符(主要用于环境变量中分割多个路径)。-
Windows 下是
; -
Linux 下是
:
-
扩展知识 - 最佳实践:
永远使用拼接的方式构建路径,或者使用 File 的构造方法。
// 推荐写法
String path = "data" + File.separator + "images" + File.separator + "logo.png";
3. 详解:构造方法
(对应您提供的图1内容)
File 类有多种“出生”方式(构造器),这里详细解释三种:
3.1 File(String pathname)
这是最直接的方式。
File f1 = new File("D:\\Files\\test.txt"); // 绝对路径
File f2 = new File("src/Main.java"); // 相对路径(相对于项目根目录)
3.2 File(String parent, String child)
将父路径和子路径分开传,Java 会自动帮你加上正确的分隔符。
String parent = "D:\\Games";
String child = "Start.exe";
File f3 = new File(parent, child);
// 等同于 D:\Games\Start.exe
场景:你有一个文件夹路径,然后想遍历里面的文件名拼接成完整路径时很有用。
3.3 File(File parent, String child)
跟上面类似,但父路径本身就是一个 File 对象。
File dir = new File("D:\\Games");
File f4 = new File(dir, "Start.exe");
场景:这种方式更灵活,因为 dir 对象可以先进行校验(比如检查 dir.exists()),确认父目录存在后再创建子文件对象。
4. 详解:File 类的常用方法
(对应您提供的图2内容,这里是重点中的重点)
4.1 获取路径与名称 (Get系列)
| 方法 | 说明 | 示例 (假设当前在 C:\Project) |
|
|
获取文件名或最后以及目录名 |
|
|
|
获取构造时传入的路径字符串 |
|
|
|
获取绝对路径(带盘符) |
-> "C:\Project\src\a.txt" |
|
|
获取父级路径字符串 |
-> "src" |
扩展知识 - getCanonicalPath():
图片中提到了这个方法。它比 getAbsolutePath 更强。
-
假设路径是
C:\Project\src\..\bin\a.exe(其中..表示上一级)。 -
getAbsolutePath会傻傻地把这个带..的字符串打印出来。 -
getCanonicalPath会计算出真实路径:C:\Project\bin\a.exe。它会解析.和..。
4.2 判断功能 (Is/Can系列)
-
exists(): 最重要的方法。操作文件前,永远先判断它存不存在! -
isDirectory(): 是不是文件夹? -
isFile(): 是不是标准文件?-
注意:电脑上除了文件和文件夹,还有“特殊文件”(如设备文件),但在常规开发中,通常
isFile()为真则isDirectory()为假,反之亦然(前提是 exists 为真)。
-
-
canRead()/canWrite(): 权限检查。Linux 系统下经常出现文件存在但无法读取(Permission Denied)的情况,用这个可以预判。
4.3 创建与删除 (Create/Delete系列)
-
createNewFile(): 创建空文件。-
坑点 1: 只有文件不存在时才创建,返回 true;如果已存在,返回 false(不报错,也不覆盖)。
-
坑点 2: 如果父目录不存在(比如
new File("A/B/c.txt"),但文件夹 A 都不存在),会抛出IOException: 系统找不到指定的路径。所以通常要先创建目录。
-
-
mkdir(): 创建目录 (Make Directory)。只能创建一级。如果父级不存在,创建失败,返回 false。 -
mkdirs(): 推荐使用。创建多级目录。如果new File("A/B/C"),它会把 A、B、C 全都建好。 -
delete(): 删除文件或目录。-
致命坑点: 删除目录时,目录必须是空的!如果文件夹里有东西,Java 为了安全禁止直接删除,必须先递归删除里面的所有内容。
-
-
deleteOnExit(): 这是一个神奇的方法。它不马上删,而是注册一个“钩子”,等 Java 虚拟机完全退出(程序跑完)时再删。常用于程序运行时产生的临时缓存文件,程序结束自动清理。
4.4 目录列表 (List系列)
-
list(): 返回String[]。只包含文件名字,比如["a.txt", "b.jpg"]。 -
listFiles(): 返回File[]。包含完整的 File 对象。-
扩展:
listFiles()非常强大,它还可以接收过滤器FileFilter。 -
举例: 只想列出 .jpg 图片?
File[] images = dir.listFiles(new FilenameFilter() { @Override public boolean accept(File dir, String name) { return name.endsWith(".jpg"); } }); -
5. 扩展知识点:新手常遇到的“坑”与进阶
5.1 相对路径的基准点在哪里?
当你在代码中写 new File("test.txt") 时,这个文件到底建在哪里了?
-
在 IDEA/Eclipse 中:通常是在你的项目根目录下(跟
src文件夹同级)。 -
在命令行运行 jar 包时:在你的 CMD/终端 当前所在的目录下。
-
扩展:可以使用
System.getProperty("user.dir")来查看当前的基准工作目录。
5.2 异常处理 (Try-Catch)
IO 操作属于“受检异常”(Checked Exception)。Java 编译器强制要求你处理。
为什么?因为 IO 是不可控的。
-
U盘突然被拔了。
-
硬盘满了。
-
文件被另一个程序(如 Excel)锁定了。
所以,凡是涉及 IO 的代码,都要用 try-catch 包裹,或者在方法签名上抛出 throws IOException。
5.3 递归 (Recursion)
面试常考题:如何遍历一个文件夹下的所有文件(包括子文件夹里的)?
listFiles() 只能看当前这一层。如果要看所有的,需要用递归。
public void printAllFiles(File dir) {
File[] files = dir.listFiles();
if (files != null) {
for (File f : files) {
if (f.isFile()) {
System.out.println(f.getName());
} else {
// 如果是文件夹,自己调用自己(递归)
printAllFiles(f);
}
}
}
}
5.4 Java NIO (New IO) - 未来的方向
虽然我们现在学的是 java.io.File,但从 Java 7 开始,官方引入了 java.nio.file.Path 和 java.nio.file.Files 工具类。
-
File类虽然经典,但有一些缺点(比如报错信息不详细,性能略低)。 -
NIO 提供了更现代的 API,比如
Files.createDirectory(),Files.copy(),Files.move()。 -
新手建议:先学透
File类,因为它是基础,很多老项目和框架依然大量使用它。等你熟练了,再学习 NIO 会非常轻松。
6. 总结
-
File 不存数据:它只是文件系统的一个“影子”对象。
-
路径分隔符:用
File.separator走遍天下。 -
创建逻辑:先检查
exists(),再判断是用mkdir()还是createNewFile()。 -
删除逻辑:删目录前必须清空目录。
-
安全第一:时刻准备处理
IOException。
更多推荐


所有评论(0)