Java学习-IO流-捕获异常的方式
try{
FileOutputStream fos = new FileOutputStream("xx.txt");
fos.write(97);
fos.close();
}catch(IOException e){
e.printStackTrace();
}
若运行到fos.write(97);
抛出异常,运行e.printStackTrace();
,则无法运行fos.close();
解决方案: finally 里面的代码一定被执行,除非虚拟机停止
try{
FileOutputStream fos = new FileOutputStream("xx.txt");
fos.write(97);
}catch(IOException e){
e.printStackTrace();
}finally{
fos.close();
}
除非JVM停止:System.exit(0);
,则不会执行 finally 内的代码
try{
FileOutputStream fos = new FileOutputStream("xx.txt");
fos.write(97);
System.exit(0);
}catch(IOException e){
e.printStackTrace();
}finally{
fos.close();
}
改写复制文件代码
1.将复制文件的代码放入 try 中,释放资源的代码放入 finally 中
try{
FileInputStream fis = new FileInputStream("...\\xx.mp4");
FileOutputStream fos = new FileOutputStream("...\\copy.mp4");
int len;
byte[] bytes = new byte[1024*1024*5];
while((len = fis.read(bytes)) != -1){
fos.write(bytes,o,len);
}
}catch(IOException e){
e.printStackTrace();
}finally{
fos.close();
fis.close();
}
2.报错原因: fis 和 fos 都是局部变量。但将 fis 和 fos 的定义放到 try 外面,会忽略创建对象时发生编译异常的情况
FileInputStream fis = new FileInputStream("...\\xx.mp4");
FileOutputStream fos = new FileOutputStream("...\\copy.mp4");
try{...}
}catch(IOException e){
e.printStackTrace();
}finally{
fos.close();
fis.close();
}
3.解决方案: try 外部定义对象,try 内部创建对象
FileInputStream fis;
FileOutputStream fos;
try{
fis = new FileInputStream("...\\xx.mp4");
fos = new FileOutputStream("...\\copy.mp4");
...
}catch(IOException e){
e.printStackTrace();
}finally{
fos.close();
fis.close();
}
4.报错: fos might not have been initialized
分析原因: fis 和 fos 初始化为 null,close() 报错:close()也会有异常,需要进行异常处理
FileInputStream fis = null;
FileOutputStream fos = null;
try{
fis = new FileInputStream("...\\xx.mp4");
fos = new FileOutputStream("...\\copy.mp4");
...
}catch(IOException e){
e.printStackTrace();
}finally{
try{fos.close();}catch(IOException e){e.printStackTrace();}
try{fis.close();}catch(IOException e){e.printStackTrace();}
}
5.如果输入文件xx.mp4
不存在,会出现NullPointerException
空指针异常,fis 依然是 null,在 finally 中执行fis.close()
会报空指针异常
解决方案: 对 fis 和 fos 做非空判断
FileInputStream fis = null;
FileOutputStream fos = null;
try{
fis = new FileInputStream("...\\xx.mp4");
fos = new FileOutputStream("...\\copy.mp4");
...
}catch(IOException e){
e.printStackTrace();
}finally{
if(fos != null){
try{fos.close();}catch(IOException e){e.printStackTrace();}
}
if(fis != null){
try{fis.close();}catch(IOException e){e.printStackTrace();}
}
}
简化方案
分析问题: 释放资源部分的代码太复杂
解决方案: AutoCloseable:特定情况下可以自动释放资源
JDK7写法:
try(创建流对象1;创建流对象2){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
JDK9写法:
创建流对象1;
创建流对象2;
try(流1;流2){
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}
注意: 对象类必须实现 AutoCloseable 接口
JDK7写法:
try(FileInputStream fis = new FileInputStream("...\\xx.mp4");
FileOutputStream fos = new FileOutputStream("...\\copy.mp4")){
int len;
byte[] bytes = new byte[1024*1024*5];
while((len = fis.read(bytes)) != -1){fos.write(bytes,o,len);}
}catch(IOException e){e.printStackTrace();}
JDK9写法:
FileInputStream fis = new FileInputStream("...\\xx.mp4");
FileOutputStream fos = new FileOutputStream("...\\copy.mp4");
try(fis;fos){
int len;
byte[] bytes = new byte[1024*1024*5];
while((len = fis.read(bytes)) != -1){fos.write(bytes,o,len);}
}catch(IOException e){e.printStackTrace();}