前言
文件是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 文件操作场景。如果需要处理二进制文件(如图片、视频)、文件复制 / 移动、文件属性修改等进阶操作,可在评论区留言,后续会补充对应的示例。文章如有错误欢迎私信我,我会及时解决,如果我的内容对你有帮助和启发,请点赞、评论、收藏。你们的支持就是我更新最大的动力,那么我们下期再见!
发表评论