JavaFile:一篇文章教你学会用Java程序操作文件
目录
文件是IO流乃至多线程的基础,学好文件这一板块可以为我们后续进一步学习IO流和多线程打下坚实的基础。在 Java 开发中,文件操作是高频且基础的核心技能 —— 无论是读取配置文件、生成日志、导出报表,还是处理用户上传的文件,都离不开对文件的创建、读取、写入、删除等操作。本文将从「实用场景」出发,手把手教你掌握 Java 文件操作的核心方法,从传统 IO 到 NIO.2,兼顾基础与最佳实践,新手也能快速上手。
一、前置知识:Java 文件操作的核心 API
Java 提供了两套核心文件操作体系,我们先理清它们的定位,避免用错工具:
| 体系 | 核心包 / 类 | 特点 | 适用场景 |
|---|---|---|---|
| 传统 IO | java.io.File、FileReader、FileWriter | 兼容性好,API 偏底层 | 简单文件操作、兼容老项目 |
| NIO.2 | java.nio.file(Paths、Files) | Java 7 新增,API 简洁、功能强、效率高 | 新项目优先使用,支持批量操作、文件属性管理 |
本文以NIO.2为主(推荐),同时补充传统 IO 的核心用法,满足不同场景需求。
二、实战:文件操作核心场景(附完整代码)
所有示例代码均可直接复制到 IDE 中运行,建议先创建测试目录 / 文件,跟着步骤实操。
场景 1:基础操作(创建、删除、判断文件 / 目录)
这是文件操作的「基本功」,比如创建配置文件、判断文件是否存在、删除临时文件等。
import java.io.File; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; public class FileBasicOperations { public static void main(String[] args) { // ========== 1. 传统IO(File类) ========== // 定义文件路径:Windows用\\(转义)或/,Linux/Mac用/ File file = new File("test.txt"); try { // 创建文件(不存在则创建,存在则返回false) if (file.createNewFile()) { System.out.println("文件创建成功:" + file.getAbsolutePath()); } else { System.out.println("文件已存在"); } // 核心判断:文件/目录类型 System.out.println("是否是文件:" + file.isFile()); System.out.println("是否是目录:" + file.isDirectory()); // 创建目录:mkdir(单层)、mkdirs(多层,推荐) File dir = new File("testDir/subDir"); if (dir.mkdirs()) { System.out.println("多层目录创建成功:" + dir.getAbsolutePath()); } // 删除文件/目录(目录需为空才能删除) if (file.delete()) { System.out.println("文件删除成功"); } } catch (Exception e) { e.printStackTrace(); // 捕获IO异常(权限不足、路径不存在等) } // ========== 2. NIO.2(推荐) ========== Path path = Paths.get("test_nio.txt"); try { // 创建文件(先判断是否存在,避免重复创建) if (!Files.exists(path)) { Files.createFile(path); System.out.println("NIO创建文件成功:" + path.toAbsolutePath()); } // 创建多层目录(无需区分单层/多层) Path dirPath = Paths.get("testDirNio/subDir"); if (!Files.exists(dirPath)) { Files.createDirectories(dirPath); System.out.println("NIO创建目录成功"); } // 删除文件/目录(支持非空目录?不,需手动遍历删除子文件) if (Files.exists(path)) { Files.delete(path); System.out.println("NIO删除文件成功"); } } catch (Exception e) { e.printStackTrace(); } } } 关键说明:
- 路径适配:推荐用
Paths.get("目录", "子目录", "文件.txt"),自动适配不同系统的分隔符; - 异常处理:文件操作必然涉及 IO 异常,必须捕获或声明抛出;
- 目录删除:
delete()只能删除空目录,非空目录需先遍历删除子文件 / 子目录。
场景 2:文本文件读取(最常用)
读取配置文件、日志文件、用户上传的文本等,NIO.2 的Files.readAllLines是最优解。
import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; public class FileReadExample { public static void main(String[] args) { String filePath = "read_test.txt"; // 先创建该文件并写入测试内容 // 方式1:一次性读取所有行(推荐,简洁) try { // 指定UTF-8编码,避免中文乱码 List<String> lines = Files.readAllLines(Paths.get(filePath), StandardCharsets.UTF_8); for (String line : lines) { System.out.println("读取到行:" + line); } } catch (Exception e) { e.printStackTrace(); } // 方式2:读取为字节数组(兼容文本/二进制文件) try { byte[] content = Files.readAllBytes(Paths.get(filePath)); String contentStr = new String(content, StandardCharsets.UTF_8); System.out.println("完整内容:\n" + contentStr); } catch (Exception e) { e.printStackTrace(); } } } 关键说明:
- 编码指定:必须显式指定
StandardCharsets.UTF_8,否则会使用系统默认编码,导致中文乱码; - 大文件注意:
readAllLines/readAllBytes适合小文件(几十 MB 内),大文件需用流逐行读取(下文补充)。
场景 3:文本文件写入(覆盖 / 追加)
生成日志、导出数据、写入配置等场景,核心是「覆盖写入」和「追加写入」。
import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; import java.util.List; public class FileWriteExample { public static void main(String[] args) { String filePath = "write_test.txt"; // 要写入的内容(按行存储) List<String> content = Arrays.asList("Java文件操作", "作者:新手学习", "时间:2026"); try { // 方式1:覆盖写入(文件不存在则创建,存在则清空原有内容) Files.write(Paths.get(filePath), content, StandardCharsets.UTF_8); System.out.println("覆盖写入成功"); // 方式2:追加写入(保留原有内容,在末尾添加) List<String> appendContent = Arrays.asList("", "——追加的内容"); // 空行分隔 Files.write( Paths.get(filePath), appendContent, StandardCharsets.UTF_8, java.nio.file.StandardOpenOption.APPEND // 追加模式 ); System.out.println("追加写入成功"); } catch (Exception e) { e.printStackTrace(); } } } 场景 4:遍历目录下的所有文件
比如批量处理某目录下的所有 Excel 文件、统计日志文件数量等,NIO.2 的Files.walk非常高效。
import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.stream.Stream; public class DirectoryTraverseExample { public static void main(String[] args) { String dirPath = "testDir"; // 目标目录 // 遍历目录(包括子目录),筛选所有文件 try (Stream<Path> walk = Files.walk(Paths.get(dirPath))) { walk.filter(Files::isRegularFile) // 只保留文件(排除目录) .filter(path -> path.toString().endsWith(".txt")) // 筛选txt文件 .forEach(path -> System.out.println("符合条件的文件:" + path.toAbsolutePath())); } catch (Exception e) { e.printStackTrace(); } } } 扩展:大文件读写(避免内存溢出)
如果文件大小超过 100MB,不能用readAllLines一次性读取,需用「流」逐行处理:
import java.io.BufferedReader; import java.io.BufferedWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; public class BigFileOperation { public static void main(String[] args) { String srcPath = "big_file.txt"; // 大文件路径 String destPath = "copy_big_file.txt"; // 复制后的文件 // 逐行读取+逐行写入(内存占用极低) try (BufferedReader br = Files.newBufferedReader(Paths.get(srcPath), StandardCharsets.UTF_8); BufferedWriter bw = Files.newBufferedWriter(Paths.get(destPath), StandardCharsets.UTF_8)) { String line; while ((line = br.readLine()) != null) { // 可在此处处理每行内容(比如过滤、修改) bw.write(line); bw.newLine(); // 换行 } System.out.println("大文件复制完成"); } catch (Exception e) { e.printStackTrace(); } } } 三、避坑指南:新手常犯的错误
- 中文乱码:未指定编码,默认使用系统编码(Windows 是 GBK,Linux 是 UTF-8),解决:所有读写操作显式指定
StandardCharsets.UTF_8; - 路径错误:硬编码 Windows 路径(如
C:\\test.txt),Linux 下运行报错,解决:用Paths.get("C:", "test.txt")适配系统; - 资源未关闭:传统 IO 的
FileInputStream未关闭导致文件被占用,解决:用try-with-resources语法(自动关闭资源); - 权限问题:写入系统目录(如 C 盘根目录)报错,解决:选择有写入权限的目录(如项目根目录、用户目录)。
四、总结
- Java 文件操作优先使用
java.nio.file(NIO.2),API 简洁且效率高,核心类是Paths(路径)和Files(操作); - 小文件用
readAllLines/write一次性处理,大文件用BufferedReader/BufferedWriter逐行处理; - 所有文件操作必须处理 IO 异常,显式指定 UTF-8 编码,避免乱码和兼容性问题。
掌握以上内容,你就能应对 90% 的 Java 文件操作场景。如果需要处理二进制文件(如图片、视频)、文件复制 / 移动、文件属性修改等进阶操作,可在评论区留言,后续会补充对应的示例。文章如有错误欢迎私信我,我会及时解决,如果我的内容对你有帮助和启发,请点赞、评论、收藏。你们的支持就是我更新最大的动力,那么我们下期再见!