Java文件导入与打开全攻略 从基础语法到实战应用详解 告别新手困惑轻松掌握文件操作技巧

引言:为什么Java文件操作如此重要?
在Java编程中,文件操作是最基础也是最核心的技能之一。无论你是开发桌面应用、Web服务,还是大数据处理程序,几乎都离不开文件的读写操作。很多新手在面对Java文件操作时常常感到困惑:该使用
FileInputStream
还是
FileReader
?
Files
工具类和传统IO流有什么区别?如何优雅地处理异常和资源关闭?
本文将从最基础的语法讲起,通过大量实战代码示例,带你全面掌握Java文件操作的精髓。我们将深入探讨Java IO体系、NIO.2新特性、以及实际开发中的最佳实践,让你彻底告别新手困惑,轻松应对各种文件操作场景。
1. Java IO体系架构概览
1.1 传统IO流的分类
Java的IO操作主要分为字节流和字符流两大体系,理解这两者的区别是掌握文件操作的第一步。
字节流(Byte Stream)
:
用于处理二进制数据,如图片、音频、视频等
核心类:
InputStream
和
OutputStream
适合所有类型的文件操作
字符流(Character Stream)
:
专门用于处理文本文件
核心类:
Reader
和
Writer
自动处理字符编码转换
import java.io.*;

public class IOStreamExample {
public static void main(String[] args) {
// 字节流示例:复制任意类型的文件
try (FileInputStream fis = new FileInputStream(“source.jpg”);
FileOutputStream fos = new FileOutputStream(“destination.jpg”)) {

byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
System.out.println(“文件复制完成!”);

} catch (IOException e) {
e.printStackTrace();
}

// 字符流示例:读取文本文件
try (FileReader fr = new FileReader(“text.txt”);
BufferedReader br = new BufferedReader(fr)) {

String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}

} catch (IOException e) {
e.printStackTrace();
}
}
}
1.2 装饰器模式的应用
Java IO流采用了装饰器模式,可以通过组合不同的流来增强功能。这种设计非常灵活,但也容易让新手混淆。
// 装饰器模式的典型应用
public class DecoratorExample {
public static void main(String[] args) {
try {
// 基础文件流
FileInputStream fis = new FileInputStream(“data.bin”);

// 缓冲流增强性能
BufferedInputStream bis = new BufferedInputStream(fis);

// 数据流增强功能
DataInputStream dis = new DataInputStream(bis);

// 读取基本数据类型
int number = dis.readInt();
double value = dis.readDouble();

dis.close(); // 关闭最外层流会自动关闭所有装饰流

} catch (IOException e) {
e.printStackTrace();
}
}
}
2. 文件导入与打开的基础操作
2.1 使用File类进行文件操作
File
类是Java文件操作的基础,虽然它不直接提供读写功能,但在文件管理和路径操作方面非常有用。
import java.io.File;
import java.io.IOException;
import java.util.Date;

public class FileOperationsExample {
public static void main(String[] args) {
// 创建File对象
File file = new File(“example.txt”);

// 检查文件是否存在
if (!file.exists()) {
try {
// 创建新文件
boolean created = file.createNewFile();
if (created) {
System.out.println(“文件创建成功!”);
}
} catch (IOException e) {
e.printStackTrace();
}
}

// 文件属性获取
System.out.println(“文件名: ” + file.getName());
System.out.println(“文件路径: ” + file.getAbsolutePath());
System.out.println(“文件大小: ” + file.length() + ” 字节”);
System.out.println(“最后修改时间: ” + new Date(file.lastModified()));
System.out.println(“是否可读: ” + file.canRead());
System.out.println(“是否可写: ” + file.canWrite());

// 文件重命名
File newFile = new File(“renamed_example.txt”);
if (file.renameTo(newFile)) {
System.out.println(“文件重命名成功!”);
}

// 删除文件
if (newFile.delete()) {
System.out.println(“文件删除成功!”);
}
}
}
2.2 文件打开与读取的完整流程
下面是一个完整的文件打开和读取示例,包含异常处理和资源管理:
import java.io.*;

public class FileReadExample {
public static void main(String[] args) {
String filePath = “sample.txt”;

// 方式1:使用try-catch-resources自动关闭资源(推荐)
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
int lineNumber = 0;
while ((line = reader.readLine()) != null) {
lineNumber++;
System.out.printf(“第%d行: %s%n”, lineNumber, line);
}
} catch (FileNotFoundException e) {
System.err.println(“文件未找到: ” + filePath);
} catch (IOException e) {
System.err.println(“读取文件时发生错误: ” + e.getMessage());
}

// 方式2:逐字符读取(效率较低,仅作演示)
try (FileReader fr = new FileReader(filePath)) {
int character;
while ((character = fr.read()) != -1) {
System.out.print((char) character);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.3 文件写入操作详解
文件写入同样需要谨慎处理异常和资源,以下是几种常见的写入方式:
import java.io.*;

public class FileWriteExample {
public static void main(String[] args) {
String filePath = “output.txt”;

// 方式1:覆盖写入
try (PrintWriter writer = new PrintWriter(new FileWriter(filePath))) {
writer.println(“第一行内容”);
writer.println(“第二行内容”);
writer.printf(“格式化输出: %s – %d%n”, “测试”, 123);
writer.write(“直接写入字符串”);
} catch (IOException e) {
e.printStackTrace();
}

// 方式2:追加写入
try (FileWriter fw = new FileWriter(filePath, true); // true表示追加模式
BufferedWriter bw = new BufferedWriter(fw)) {

bw.newLine(); // 添加换行
bw.write(“这是追加的内容”);
bw.flush(); // 确保数据写入磁盘

} catch (IOException e) {
e.printStackTrace();
}

// 方式3:字节流写入(适合二进制数据)
try (FileOutputStream fos = new FileOutputStream(“data.bin”)) {
byte[] data = {1, 2, 3, 4, 5};
fos.write(data);
} catch (IOException e) {
e.printStackTrace();
}
}
}
3. NIO.2文件操作(Java 7+推荐)
3.1 Files工具类的强大功能
从Java 7开始,引入了NIO.2(New IO 2)API,提供了更简单、更强大的文件操作方式。这是现代Java开发的首选。
import java.nio.file.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.stream.Collectors;
import java.io.IOException;

public class NIO2Example {
public static void main(String[] args) {
Path path = Paths.get(“nio2_example.txt”);

try {
// 1. 读取所有行(一行代码搞定)
List lines = Files.readAllLines(path, StandardCharsets.UTF_8);
System.out.println(“文件内容: ” + lines);

// 2. 写入所有内容
List newLines = List.of(“第一行”, “第二行”, “第三行”);
Files.write(path, newLines, StandardCharsets.UTF_8);

// 3. 追加写入
Files.write(path, List.of(“追加行”), StandardCharsets.UTF_8, StandardOpenOption.APPEND);

// 4. 复制文件
Path source = Paths.get(“source.txt”);
Path target = Paths.get(“target.txt”);
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);

// 5. 移动/重命名文件
Files.move(source, Paths.get(“moved.txt”), StandardCopyOption.REPLACE_EXISTING);

// 6. 删除文件
Files.deleteIfExists(target);

// 7. 检查文件属性
System.out.println(“文件大小: ” + Files.size(path));
System.out.println(“是否是目录: ” + Files.isDirectory(path));
System.out.println(“是否是普通文件: ” + Files.isRegularFile(path));

} catch (IOException e) {
e.printStackTrace();
}
}
}
3.2 文件遍历和目录操作
NIO.2提供了强大的目录遍历能力,支持通配符和递归搜索:
import java.nio.file.*;
import java.io.IOException;
import java.util.stream.Stream;

public class DirectoryOperations {
public static void main(String[] args) {
Path dir = Paths.get(“.”);

try {
// 1. 遍历当前目录下的所有文件
System.out.println(“=== 当前目录下的所有文件 ===”);
try (Stream stream = Files.list(dir)) {
stream.filter(Files::isRegularFile)
.forEach(p -> System.out.println(p.getFileName()));
}

// 2. 递归遍历所有子目录
System.out.println(“\n=== 递归遍历所有Java文件 ===”);
try (Stream stream = Files.walk(dir)) {
stream.filter(p -> p.toString().endsWith(“.java”))
.forEach(p -> System.out.println(p));
}

// 3. 使用通配符搜索
System.out.println(“\n=== 搜索所有txt文件 ===”);
PathMatcher matcher = FileSystems.getDefault().getPathMatcher(“glob:**/*.txt”);
try (Stream stream = Files.walk(dir)) {
stream.filter(matcher::matches)
.forEach(p -> System.out.println(p));
}

// 4. 创建目录和多级目录
Path newDir = Paths.get(“test/subdir/nested”);
Files.createDirectories(newDir); // 自动创建所有不存在的父目录
System.out.println(“\n目录创建成功: ” + newDir);

} catch (IOException e) {
e.printStackTrace();
}
}
}
3.3 文件属性和权限管理
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;

public class FileAttributesExample {
public static void main(String[] args) {
Path path = Paths.get(“example.txt”);

try {
// 获取基本属性
BasicFileAttributes attrs = Files.readAttributes(path, BasicFileAttributes.class);
System.out.println(“创建时间: ” + attrs.creationTime());
System.out.println(“最后访问时间: ” + attrs.lastAccessTime());
System.out.println(“最后修改时间: ” + attrs.lastModifiedTime());
System.out.println(“文件大小: ” + attrs.size());

// 设置文件权限(Unix/Linux系统)
Set perms = PosixFilePermissions.fromString(“rw-r–r–“);
Files.setPosixFilePermissions(path, perms);

// 读取权限
Set currentPerms = Files.getPosixFilePermissions(path);
System.out.println(“当前权限: ” + PosixFilePermissions.toString(currentPerms));

} catch (IOException e) {
// Windows系统可能不支持Posix权限
System.out.println(“注意: 某些属性操作在Windows上可能不支持”);
}
}
}
4. 实战应用:完整项目示例
4.1 日志文件分析器
下面是一个实用的日志文件分析器,综合运用了多种文件操作技巧:
import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.regex.*;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class LogAnalyzer {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:ss”);

public static void main(String[] args) {
String logFile = “application.log”;

// 1. 创建示例日志文件
createSampleLog(logFile);

// 2. 分析日志
try {
analyzeLog(logFile);
} catch (IOException e) {
System.err.println(“分析失败: ” + e.getMessage());
}
}

private static void createSampleLog(String filename) {
try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
writer.println(“2024-01-15 10:30:25 [INFO] Application started”);
writer.println(“2024-01-15 10:30:26 [DEBUG] Loading configuration”);
writer.println(“2024-01-15 10:30:27 [ERROR] Database connection failed”);
writer.println(“2024-01-15 10:30:28 [WARN] High memory usage detected”);
writer.println(“2024-01-15 10:30:29 [INFO] User login successful”);
writer.println(“2024-01-15 10:30:30 [ERROR] File not found: config.properties”);
} catch (IOException e) {
e.printStackTrace();
}
}

private static void analyzeLog(String filename) throws IOException {
Map levelCount = new HashMap<>();
List errorMessages = new ArrayList<>();

try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = reader.readLine()) != null) {
// 使用正则表达式解析日志级别
Pattern pattern = Pattern.compile(“\\[(INFO|DEBUG|WARN|ERROR)\\]”);
Matcher matcher = pattern.matcher(line);

if (matcher.find()) {
String level = matcher.group(1);
levelCount.put(level, levelCount.getOrDefault(level, 0) + 1);

// 收集错误信息
if (“ERROR”.equals(level)) {
errorMessages.add(line);
}
}
}
}

// 输出分析结果
System.out.println(“=== 日志分析报告 ===”);
System.out.println(“生成时间: ” + LocalDateTime.now().format(formatter));
System.out.println(“\n日志级别统计:”);
levelCount.forEach((level, count) ->
System.out.printf(” %s: %d 条%n”, level, count)
);

if (!errorMessages.isEmpty()) {
System.out.println(“\n错误日志详情:”);
errorMessages.forEach(System.out::println);
}

// 将分析结果保存到新文件
saveAnalysisReport(levelCount, errorMessages);
}

private static void saveAnalysisReport(Map counts, List errors) throws IOException {
String reportFile = “log_analysis_report.txt”;

try (PrintWriter writer = new PrintWriter(new FileWriter(reportFile))) {
writer.println(“日志分析报告”);
writer.println(“生成时间: ” + LocalDateTime.now().format(formatter));
writer.println(“=”.repeat(50));

writer.println(“\n日志级别统计:”);
counts.forEach((level, count) ->
writer.printf(“%s: %d 条%n”, level, count)
);

if (!errors.isEmpty()) {
writer.println(“\n错误详情:”);
errors.forEach(writer::println);
}
}

System.out.println(“\n分析报告已保存到: ” + reportFile);
}
}
4.2 配置文件读取器
import java.io.*;
import java.util.Properties;
import java.nio.file.*;

public class ConfigReader {
private Properties properties;

public ConfigReader(String configFile) throws IOException {
properties = new Properties();

// 支持多种方式加载配置
if (Files.exists(Paths.get(configFile))) {
try (FileInputStream fis = new FileInputStream(configFile)) {
properties.load(fis);
}
} else {
// 如果文件不存在,加载默认配置
loadDefaultConfig();
}
}

private void loadDefaultConfig() {
properties.setProperty(“database.url”, “jdbc:mysql://localhost:3306/mydb”);
properties.setProperty(“database.username”, “root”);
properties.setProperty(“database.password”, “password”);
properties.setProperty(“app.port”, “8080”);
properties.setProperty(“log.level”, “INFO”);
}

public String getProperty(String key) {
return properties.getProperty(key);
}

public String getProperty(String key, String defaultValue) {
return properties.getProperty(key, defaultValue);
}

public void setProperty(String key, String value) {
properties.setProperty(key, value);
}

public void saveConfig(String filename) throws IOException {
try (FileOutputStream fos = new FileOutputStream(filename)) {
properties.store(fos, “Application Configuration”);
}
}

public static void main(String[] args) {
try {
// 创建配置读取器
ConfigReader reader = new ConfigReader(“app.properties”);

// 读取配置
System.out.println(“数据库URL: ” + reader.getProperty(“database.url”));
System.out.println(“应用端口: ” + reader.getProperty(“app.port”, “8080”));

// 修改并保存配置
reader.setProperty(“app.version”, “1.0.0”);
reader.setProperty(“log.level”, “DEBUG”);
reader.saveConfig(“app.properties”);

System.out.println(“配置已保存!”);

} catch (IOException e) {
System.err.println(“配置操作失败: ” + e.getMessage());
}
}
}
5. 高级技巧与最佳实践
5.1 大文件处理策略
处理大文件时,必须避免一次性加载到内存,应该使用流式处理:
import java.io.*;
import java.nio.file.*;
import java.util.stream.*;

public class LargeFileProcessor {

// ❌ 错误做法:一次性读取大文件到内存
public static void badApproach(String filename) throws IOException {
// 这会导致内存溢出!
List allLines = Files.readAllLines(Paths.get(filename));
// 处理…
}

// ✅ 正确做法:流式处理
public static void goodApproach(String filename) throws IOException {
try (Stream lines = Files.lines(Paths.get(filename))) {
lines.filter(line -> line.contains(“ERROR”))
.forEach(System.out::println);
}
}

// ✅ 另一种正确做法:逐行读取
public static void processLineByLine(String filename) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = reader.readLine()) != null) {
// 逐行处理,内存占用恒定
processLine(line);
}
}
}

private static void processLine(String line) {
// 实际处理逻辑
if (line.length() > 100) {
System.out.println(“长行: ” + line.substring(0, 100) + “…”);
}
}

public static void main(String[] args) {
// 创建一个大文件用于测试
String largeFile = “large_log.txt”;
createLargeFile(largeFile, 10000); // 1万行

try {
System.out.println(“=== 流式处理大文件 ===”);
goodApproach(largeFile);
} catch (IOException e) {
e.printStackTrace();
}
}

private static void createLargeFile(String filename, int lines) {
try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) {
for (int i = 0; i < lines; i++) { writer.printf("Line %d: %s%n", i, i % 10 == 0 ? "ERROR" : "INFO"); } } catch (IOException e) { e.printStackTrace(); } } } 5.2 异常处理的黄金法则 import java.io.*; import java.nio.file.*; public class ExceptionHandlingExample { // ❌ 不推荐:吞掉异常 public static void badExceptionHandling() { try { // some code } catch (IOException e) { // 什么都不做,或者只打印堆栈 e.printStackTrace(); } } // ✅ 推荐:具体处理并记录 public static void goodExceptionHandling() { try { Files.readAllLines(Paths.get("config.txt")); } catch (NoSuchFileException e) { System.err.println("配置文件不存在: " + e.getFile()); // 使用默认配置 } catch (AccessDeniedException e) { System.err.println("没有权限访问文件: " + e.getFile()); // 提示用户修改权限 } catch (IOException e) { System.err.println("读取文件时发生未知错误: " + e.getMessage()); // 记录到日志系统 logger.error("文件操作失败", e); } } // ✅ 最佳实践:使用try-with-resources + 具体异常处理 public static void bestPractice(String filename) { try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (FileNotFoundException e) { System.err.println("文件未找到: " + filename); // 创建默认文件 createDefaultFile(filename); } catch (IOException e) { System.err.println("IO错误: " + e.getMessage()); // 记录日志并抛出运行时异常 throw new RuntimeException("无法读取文件", e); } } private static void createDefaultFile(String filename) { try (PrintWriter writer = new PrintWriter(new FileWriter(filename))) { writer.println("default=config"); } catch (IOException e) { System.err.println("无法创建默认文件: " + e.getMessage()); } } // 日志记录器(简化版) private static final Logger logger = new Logger(); static class Logger { public void error(String msg, Exception e) { System.err.printf("[ERROR] %s: %s%n", msg, e.getMessage()); } } public static void main(String[] args) { bestPractice("nonexistent.txt"); } } 5.3 性能优化技巧 import java.io.*; import java.nio.file.*; import java.util.Arrays; public class PerformanceOptimization { // 缓冲区大小优化 private static final int BUFFER_SIZE = 8192; // 8KB,通常是OS页面大小的倍数 // ✅ 高性能文件复制 public static void fastCopy(String source, String target) throws IOException { try (FileInputStream fis = new FileInputStream(source); FileOutputStream fos = new FileOutputStream(target)) { byte[] buffer = new byte[BUFFER_SIZE]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { fos.write(buffer, 0, bytesRead); } } } // ✅ 使用NIO的零拷贝技术(如果支持) public static void nioCopy(String source, String target) throws IOException { Path sourcePath = Paths.get(source); Path targetPath = Paths.get(target); // NIO.2在底层可能使用操作系统级的零拷贝优化 Files.copy(sourcePath, targetPath, StandardCopyOption.REPLACE_EXISTING); } // ✅ 批量操作优化 public static void batchWrite(String filename, String[] data) throws IOException { try (BufferedWriter writer = new BufferedWriter( new FileWriter(filename), BUFFER_SIZE)) { for (String line : data) { writer.write(line); writer.newLine(); } // 自动flush在close时发生,但可以手动flush writer.flush(); } } // ✅ 内存映射文件(适合超大文件随机访问) public static void memoryMappedRead(String filename) throws IOException { try (RandomAccessFile file = new RandomAccessFile(filename, "r"); FileChannel channel = file.getChannel()) { // 映射整个文件到内存 java.nio.MappedByteBuffer buffer = channel.map( java.nio.channels.FileChannel.MapMode.READ_ONLY, 0, channel.size() ); // 可以像操作数组一样操作文件 byte[] data = new byte[(int) channel.size()]; buffer.get(data); System.out.println("读取了 " + data.length + " 字节"); } } public static void main(String[] args) { try { // 创建测试文件 String source = "source.dat"; createLargeBinaryFile(source, 1024 * 1024); // 1MB // 测试复制性能 long start = System.currentTimeMillis(); fastCopy(source, "copy1.dat"); long end = System.currentTimeMillis(); System.out.println("传统复制耗时: " + (end - start) + "ms"); start = System.currentTimeMillis(); nioCopy(source, "copy2.dat"); end = System.currentTimeMillis(); System.out.println("NIO复制耗时: " + (end - start) + "ms"); } catch (IOException e) { e.printStackTrace(); } } private static void createLargeBinaryFile(String filename, int size) throws IOException { try (FileOutputStream fos = new FileOutputStream(filename)) { byte[] data = new byte[1024]; Arrays.fill(data, (byte) 0xFF); for (int i = 0; i < size / 1024; i++) { fos.write(data); } } } } 6. 常见问题与解决方案 6.1 文件路径问题 import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; public class PathHandling { public static void main(String[] args) { // 相对路径 vs 绝对路径 File relativeFile = new File("data.txt"); // 相对于当前工作目录 File absoluteFile = new File("/home/user/data.txt"); // 绝对路径 // 使用Path API(推荐) Path path1 = Paths.get("data.txt"); Path path2 = Paths.get("/home/user/data.txt"); // 路径拼接 Path configDir = Paths.get("config", "app.properties"); System.out.println("配置文件路径: " + configDir); // 获取当前工作目录 System.out.println("当前目录: " + System.getProperty("user.dir")); // 获取用户主目录 System.out.println("用户主目录: " + System.getProperty("user.home")); // 获取临时目录 System.out.println("临时目录: " + System.getProperty("java.io.tmpdir")); } } 6.2 编码问题 import java.io.*; import java.nio.charset.StandardCharsets; public class EncodingExample { public static void main(String[] args) { String content = "中文内容 - 中文内容"; String filename = "encoded.txt"; // ❌ 错误:使用平台默认编码 try (FileWriter fw = new FileWriter(filename)) { fw.write(content); // 可能在不同系统上表现不一致 } catch (IOException e) { e.printStackTrace(); } // ✅ 正确:明确指定编码(UTF-8) try (OutputStreamWriter osw = new OutputStreamWriter( new FileOutputStream(filename), StandardCharsets.UTF_8)) { osw.write(content); } catch (IOException e) { e.printStackTrace(); } // ✅ NIO方式(最推荐) try { Files.write(Paths.get(filename), List.of(content), StandardCharsets.UTF_8); } catch (IOException e) { e.printStackTrace(); } // 读取时也要指定编码 try (BufferedReader reader = new BufferedReader( new InputStreamReader( new FileInputStream(filename), StandardCharsets.UTF_8))) { String line; while ((line = reader.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } } 6.3 文件锁定与并发访问 import java.io.*; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.*; public class FileLockingExample { public static void main(String[] args) { String lockFile = "lockfile.lock"; // 线程1:获取独占锁 new Thread(() -> {
try (RandomAccessFile raf = new RandomAccessFile(lockFile, “rw”);
FileChannel channel = raf.getChannel()) {

System.out.println(“线程1尝试获取锁…”);
try (FileLock lock = channel.lock()) {
System.out.println(“线程1获取锁成功,开始处理…”);
Thread.sleep(5000); // 模拟耗时操作
System.out.println(“线程1处理完成”);
}

} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}).start();

// 线程2:尝试获取锁(会等待)
new Thread(() -> {
try {
Thread.sleep(1000); // 等待线程1先获取锁
try (RandomAccessFile raf = new RandomAccessFile(lockFile, “rw”);
FileChannel channel = raf.getChannel()) {

System.out.println(“线程2尝试获取锁…”);
try (FileLock lock = channel.lock()) {
System.out.println(“线程2获取锁成功,开始处理…”);
Thread.sleep(2000);
System.out.println(“线程2处理完成”);
}

}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
7. 总结与建议
通过本文的详细讲解和大量实战代码,相信你已经对Java文件操作有了全面深入的理解。以下是核心要点总结:
核心原则
优先使用NIO.2 API
:Files工具类更简洁、功能更强大
始终使用try-with-resources
:自动管理资源,避免内存泄漏
明确指定编码
:使用UTF-8避免跨平台问题
大文件流式处理
:避免一次性加载到内存
具体异常处理
:不要吞掉异常,要针对性处理
推荐的API选择
文本文件
:
Files.readAllLines()
/
Files.write()
大文件
:
Files.lines()
或
BufferedReader
二进制文件
:
Files.copy()
或
FileInputStream
/
FileOutputStream
配置文件
:
Properties
类
目录操作
:
Files.walk()
/
Files.list()
避免的常见错误
❌ 使用
FileReader
/
FileWriter
而不指定编码
❌ 在循环外创建BufferedReader/Writer
❌ 吞掉IOException异常
❌ 一次性读取大文件到内存
❌ 忘记关闭资源(虽然try-with-resources解决了这个问题)
希望这篇详细的指南能帮助你彻底掌握Java文件操作。记住,实践是最好的学习方式,建议你运行文中的所有代码示例,并尝试修改它们以适应你的实际需求。如果遇到问题,欢迎随时回顾本文的相关章节。
祝你编程愉快!