java中的异常与IO(异常重点)
Java 异常 + IO 完整知识点
一、Java 异常体系
- 异常分类结构
Throwable
├─ Error 错误(系统级,程序无法处理,不用捕获)
│ 如:OutOfMemoryError、StackOverflowError
└─ Exception 异常(程序可处理)
├─ 受检异常 CheckedException(编译强制捕获/抛出)
│ IO、SQL、文件、类不存在等
└─ 非受检异常 RuntimeException(运行时才报错,编译不强制处理)
空指针、数组越界、类型转换、算术除0 - 异常处理关键字:try-catch-finally、throws、throw
(1)try-catch-finally
• try:放可能出错的代码
• catch:捕获对应异常,处理逻辑
• finally:无论是否异常、是否return,一定会执行,IO流关闭写在这里
public void test() {
try {
int a = 1 / 0;
} catch (ArithmeticException e) {
System.out.println("除零异常:" + e.getMessage());
e.printStackTrace(); // 打印完整堆栈
} finally {
System.out.println("必然执行,用于关闭IO资源");
}
}
(2)throws 声明抛出
方法自己不处理,把异常抛给调用者,只用于受检异常
// IO异常是受检异常,必须throws或try-catch
public void readFile() throws IOException {
FileReader fr = new FileReader("test.txt");
}
(3)throw 手动抛出异常
主动制造异常,多用于参数校验
public void setAge(int age) {
if (age < 0) {
throw new IllegalArgumentException("年龄不能为负数");
}
}
(4)try-with-resources(Java7 推荐,IO必备)
实现 AutoCloseable 的资源(IO流),写完自动关闭,替代finally手动关流,无需手动close
try (FileReader fr = new FileReader("a.txt")) {
char c = (char) fr.read();
} catch (IOException e) {
e.printStackTrace();
}
// 离开try块自动调用fr.close(),不用写finally
3. 自定义异常
继承 Exception(受检)/RuntimeException(非受检)
// 自定义受检异常
class FileEmptyException extends Exception {
public FileEmptyException(String msg) {
super(msg);
}
}
二、Java IO 流体系
- 四大基类(分字节流/字符流)
分类 输入(读) 输出(写) 适用场景
字节流(二进制) InputStream OutputStream 图片、视频、压缩包、任意文件
字符流(文本) Reader Writer txt、java、md 纯文本
核心区别
• 字节流:操作byte,不带缓冲区,读写文件直接操作磁盘
• 字符流:操作char,自带缓冲区,不flush/close会丢失数据
- 常用IO子类
字节流
-
FileInputStream / FileOutputStream:文件原始字节读写
-
BufferedInputStream / BufferedOutputStream:缓冲包装,提速
-
ObjectInputStream / ObjectOutputStream:对象序列化读写
字符流
-
FileReader / FileWriter:文件文本读写
-
BufferedReader / BufferedWriter:带行缓冲,readLine()按行读
-
InputStreamReader / OutputStreamWriter:转换流(字节→字符,指定编码)
-
基础文件读写代码示例
示例1:字符缓冲读取文本(BufferedReader)
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class IoDemo {
public static void main(String[] args) {
// 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();
}
}
}
示例2:字节流复制文件(图片/视频通用)
try (FileInputStream fis = new FileInputStream("src.jpg");
FileOutputStream fos = new FileOutputStream("dest.jpg")) {
byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
示例3:转换流解决中文乱码(指定UTF-8)
// 字节流转字符流,手动设置编码,避免系统默认编码乱码
try (BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream("utf8.txt"), "UTF-8")
)) {
String s = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
4. IO核心注意事项(结合异常)
-
IO操作全部抛出 IOException(受检异常),必须 try-catch 或 throws
-
资源必须关闭:
• Java7+:优先 try-with-resources,自动关闭,代码简洁安全
• Java6及以下:必须在 finally 中手动调用 close(),且close也要捕获异常
-
字符流有缓冲区:写入后不调用 flush()/close(),数据留在内存,文件为空
-
文件输出流 FileOutputStream("a.txt") 会覆盖原文件;追加使用 new FileOutputStream("a.txt", true)
-
File 文件类(文件/目录操作,不属于流)
只操作文件元信息(创建、删除、判断是否存在、遍历文件夹),不读写内容
File file = new File("test.txt");
System.out.println(file.exists()); // 是否存在
file.createNewFile(); // 创建空文件,抛IOException
File dir = new File("folder");
dir.mkdirs(); // 创建多级文件夹
三、异常 + IO 综合高频考点
-
为什么IO异常是受检异常?
IO操作依赖外部磁盘文件,极易出现文件不存在、权限不足、文件损坏等外部错误,编译器强制开发者处理,避免程序无声崩溃。 -
finally 和 try-with-resources 怎么选?
Java7及以后一律用try-with-resources,代码更少、不会漏关流;finally适合不实现AutoCloseable的自定义资源。 -
字符流和字节流怎么选?
• 纯文本文件:字符流(便捷,支持按行读取)
• 图片、视频、exe、压缩包:只能字节流,字符流会损坏二进制数据
-
缓冲区丢失数据问题
BufferedWriter/FileWriter写入内容后程序直接退出,不close/flush,缓冲区数据未刷入磁盘,文件无内容;close会自动执行flush。 -
异常链:捕获IO异常后可以包装自定义异常抛出
try {
// 文件读取
} catch (IOException e) {
throw new FileEmptyException("文件读取失败", e); // 保留原始异常堆栈
}
四、易错题总结 -
忘记处理IO异常,编译直接报错(受检异常)
-
读写二进制图片使用FileReader,导致文件损坏
-
字符流写完未关闭,文件空白
-
不使用缓冲流,大文件读写速度极慢
-
没有用try-with-resources,忘记关闭流,造成文件资源泄漏
-
转换流不指定编码,Windows默认GBK读取UTF-8文件出现中文乱码

浙公网安备 33010602011771号