文件拷贝
基本代码
FileInputStream fis = new FileInputStream("D:\\itheima\\movie.mp4");
FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");
int b;
while ((b = fis.read()) != -1) {
fos.write(b);
}
//先开的流最后关闭
fos.close();
fis.close();
弊端与解决方案
- 弊端
- 一次只读写一个字节,速度太慢
-
解决方案
- 一次读取多个字节
-
FileInputStream一次读取多个字节
| 方法名称 | 说明 |
|---|---|
| public int read() | 一次读一个字节数据 |
| public int read(byte [] buffer) | 一次读取一个字节数组数据 |
- 注意
- 一次读一个字节数组的数据,每次读取会尽可能把数组装满
- 返回值:本次读取到了多少个字节数据
- 一般创建的字节数组大小为1024的整数倍
- 1024 * 1024 * 5 或 1024 * 1024 * 10
- 使用同一个字节数组存储读取的数据时,读取到的新数据会覆盖数组中的老数据,若新数据的长度小于老数据的长度,多出来的部分不会被清空
-
解决方案1:在将字节数组转换为字符串的时候,使用重载的构造方法
String str = new String(bytes, 0, len);- 解决方案2:使用write方法的重载形式,指定写入数组的开始和结束索引
fos.write(bytes[], 0, len);
-
改写代码
FileInputStream fis = new FileInputStream("D:\\itheima.mp4");
FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");
byte[] bytes = new byte[1024 * 1024 * 5];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
fos.close();
fis.close();
捕获异常
- try...catch...finally语句
- 特点:finally里面的代码一定会被执行,除非虚拟机停止
基本做法
//先创建对象,但不初始化,因为初始化也会有编译时期异常
FileInputStream fis = null;
fileOutputStream fos = null;
try {
//如果在语句块中创建对象,下面的close方法会找不到对象
fis = new FileInputStream("D:\\itheima.mp4");
fos = new FileOutputStream("myio\\copy.mp4");
byte[] bytes = new byte[1024 * 1024 * 5];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//close方法也会报编译时期异常,也要捕获
//但是如果在初始化对象时文件不存在(这个空指针异常被上面的catch捕获),但是对象中存储的还是null,此时调用close方法还会报空指针异常,所以还要加非空判断
if (fos != null) {
try {
fos.close();
} catch (IOException e){
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e){
e.printStackTrace();
}
}
}
简化方案
-
在JDK7时,Java推出了新的接口AutoCloseable
-
特点:实现这个接口后,在特定的情况下,可以自动释放资源
基本做法
try {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
} finally {
执行所有资源释放操作;
}
JDK7方案
- 资源用完最终自动释放
- 只有实现了AutoCloseAble接口的类,才能在小括号中创建对象
- FileInputStream继承自InputStream,InputStream实现了Closeable接口,Closeable继承自AutoCloseable
- FileOutputStream同理
try(创建流对象1; 创建流对象2) {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}
try(FileInputStream fis = new FileInputStream("D:\\itheima.mp4");
FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");) {
byte[] bytes = new byte[1024 * 1024 * 5];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}
JDK9方案
- 资源用完最终自动释放
创建流对象1;
创建流对象2;
try(流1; 流2) {
可能出现异常的代码;
} catch(异常类名 变量名) {
异常的处理代码;
}
//外面的编译时期异常还是
FileInputStream fis = new FileInputStream("D:\\itheima.mp4");
FileOutputStream fos = new FileOutputStream("myio\\copy.mp4");
try(fis; fos) {
byte[] bytes = new byte[1024 * 1024 * 5];
int len;
while ((len = fis.read(bytes)) != -1) {
fos.write(bytes, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}