文章目录
- 1. 异常处理与优化
- 1.1 在文件操作中使用 `try-catch`
- 1.2 `try-with-resources` 语法
- 1.3 使用 `finally `块关闭资源
- 1.4 代码健壮性与优化
- 2. 实践任务
- 2.1 改进思路
- 2.2 示例改进要点
- 2.3 检查点
- 3. 总结
- 3.1 改进后的完整代码:
- 4. 今日生词
今日学习目标:
第 6 天:异常处理与优化
学习内容
在文件操作中使用 try-catch 处理异常:
try-with-resources 语法(try (BufferedReader br = new BufferedReader(new FileReader(“test.txt”)))。
优化文件操作代码,提高健壮性:
使用 finally 关闭资源,避免内存泄漏。
实践任务
改进前一天的文件管理工具:
处理异常,如 IOException 和 FileNotFoundException。
使用 try-with-resources 确保资源关闭。
1. 异常处理与优化
1.1 在文件操作中使用 try-catch
- 基本结构
try {
// 可能抛出异常的代码
} catch (IOException e) {
// 对 IOException 的处理
}
- 常见异常类型
FileNotFoundException
:当要读取的文件不存在时抛出IOException
:文件读写过程中的其他 I/O 异常
- 使用场景
- 在文件读取(如
FileReader
、BufferedReader
)时捕获IOException
- 在文件写入(如
FileWriter
、BufferedWriter
)时捕获IOException
- 在文件读取(如
1.2 try-with-resources
语法
- 语法示例
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
- 优势
- 自动关闭资源:
try-with-resources
块结束时,Java 会自动调用资源的close()
方法 - 代码更简洁:省去显式的
finally
块来关闭流
- 自动关闭资源:
1.3 使用 finally
块关闭资源
- 传统方式
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("test.txt"));
// 文件读取操作
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 适用场景
- 在无法使用
try-with-resources
的情况(例如,Java 版本限制) - 需要在
finally
块中进行其他清理操作时
- 在无法使用
1.4 代码健壮性与优化
1.捕获并分类处理异常
- 将不同异常类型分开处理或给予不同提示,便于用户理解问题所在
2.提供用户友好提示 - 异常信息中应包含具体原因,方便排查问题
3.减少重复代码 - 将重复的异常处理逻辑提取到方法中,或使用工具类封装
2. 实践任务
改进前一天的文件管理工具:
- 处理异常,如
IOException
和FileNotFoundException
- 使用
try-with-resources
确保资源关闭
2.1 改进思路
1.使用try-with-resources
替换原有的 try-catch-finally
- 在读取文件 (
readFile
) 和写入文件(writeFile)
方法中,使用try-with-resources
自动关闭流。
2.更加细化的异常捕获 - 在文件读取时分别捕获
FileNotFoundException(
若文件不存在,给出提示) - 捕获
IOException
(若读写出错,也能给出相应提示)
3.保持程序逻辑不变 - 依然允许用户创建文件、读取内容、修改内容后保存等操作,只是让异常处理更健壮。
2.2 示例改进要点
- 示例:
readFile(File file)
方法
public static void readFile(File file) {
// try-with-resources 会自动关闭 BufferedReader
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (FileNotFoundException e) {
System.out.println("文件未找到: " + e.getMessage());
} catch (IOException e) {
System.out.println("读取文件失败: " + e.getMessage());
}
}
- 示例:
writeFile(File file, String content)
方法
public static void writeFile(File file, String content) {
// 同样使用 try-with-resources
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(content);
System.out.println("文件已保存。");
} catch (IOException e) {
System.out.println("写入文件失败: " + e.getMessage());
}
}
- 在其他需要文件操作的地方也可类比使用。
2.3 检查点
1.测试文件不存在的情况
- 输入一个不存在的路径,看是否能提示“文件未找到”,并在用户选择创建后正常创建。
2.测试文件读取失败情况 - 例如手动给文件设置只读,或放在不可访问的目录下,是否能捕获 IOException。
3.测试修改保存功能 - 修改文件内容后保存,看是否正确写入且资源关闭无误。
3. 总结
- 通过使用
try-catch
、try-with-resources
以及finally
你可以有效地处理文件读写过程中出现的各种异常,并确保资源得到正确释放。 - 改进后的文件管理工具更健壮
当用户输入了错误路径或在读写文件时遇到问题时,程序能给出清晰的提示,并且不会造成资源泄漏。 - 后续学习方向
- 更深入的异常体系:自定义异常、异常链等
- 更复杂的文件操作:如多线程读写、大文件分块处理等
3.1 改进后的完整代码:
import java.io.*;
import java.util.Scanner;
public class FileManager {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入文件路径:");
String filePath = scanner.nextLine();
File file = new File(filePath);
if (file.exists()) {
// 文件存在,读取并显示内容
System.out.println("文件存在,内容如下:");
readFile(file);
System.out.println("是否需要修改文件内容? (yes/no)");
String response = scanner.nextLine();
if (response.equalsIgnoreCase("yes") || response.equalsIgnoreCase("y")) {
System.out.println("请输入新的内容(输入单独一行 exit 表示结束):");
String newContent = readMultilineInput(scanner);
writeFile(file, newContent);
} else {
System.out.println("不修改文件内容,程序结束。");
}
} else {
// 文件不存在,询问是否创建新文件
System.out.println("文件不存在,是否创建新文件? (yes/no)");
String response = scanner.nextLine();
if (response.equalsIgnoreCase("yes") || response.equalsIgnoreCase("y")) {
// 检查并创建父目录
File parentDir = file.getParentFile();
if (parentDir != null && !parentDir.exists()) {
if (parentDir.mkdirs()) {
System.out.println("父目录创建成功。");
} else {
System.out.println("父目录创建失败,请检查路径和权限。");
}
}
try {
if (file.createNewFile()) {
System.out.println("文件创建成功。");
System.out.println("请输入要写入文件的内容(输入单独一行 exit 表示结束):");
String content = readMultilineInput(scanner);
writeFile(file, content);
} else {
System.out.println("文件创建失败或文件已存在。");
}
} catch (IOException e) {
System.out.println("文件创建失败: " + e.getMessage());
}
} else {
System.out.println("未创建文件,程序结束。");
}
}
scanner.close();
}
// 方法:使用 try-with-resources 读取文件内容并显示到控制台
public static void readFile(File file) {
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line;
System.out.println("------ 文件内容开始 ------");
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
System.out.println("------ 文件内容结束 ------");
} catch (FileNotFoundException e) {
System.out.println("文件未找到: " + e.getMessage());
} catch (IOException e) {
System.out.println("读取文件失败: " + e.getMessage());
}
}
// 方法:使用 try-with-resources 将内容写入文件
public static void writeFile(File file, String content) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(content);
System.out.println("文件已保存。");
} catch (IOException e) {
System.out.println("写入文件失败: " + e.getMessage());
}
}
// 方法:读取多行输入,以单独一行 "exit" 作为结束标识
public static String readMultilineInput(Scanner scanner) {
StringBuilder content = new StringBuilder();
String line;
while (!(line = scanner.nextLine()).equals("exit")) {
content.append(line).append(System.lineSeparator());
}
return content.toString();
}
}
- 代码改进要点
1.父目录创建
在创建新文件前,先判断文件的父目录是否存在,若不存在则调用 parentDir.mkdirs() 创建多级目录,确保路径正确。
2.使用 try-with-resources
在读取与写入文件时都使用 try-with-resources 语法,确保在操作完成后自动关闭流,避免资源泄漏。
3.异常细化处理
分别捕获 FileNotFoundException 和 IOException,为用户提供更清晰的错误提示。
4. 今日生词
1.bacteria 2.motivate 3.ingredient 4.commercial 5.penalty