Java的File类、IO流
# File类、IO流
# File类
# 主要掌握内容
# File类概述
File类的对象代表操作系统的文件(文件、文件夹),File类在java.io.File包下。
File类提供了诸如:创建文件对象代表文件,获取文件信息(大小、修改时间)、删除文件、创建文件(文件夹)等功能
# File类的使用
# 创建File对象
方法名称 | 说明 |
---|---|
public File(String pathname) | 根据文件路径创建文件对象 |
public File(String parent, String child) | 根据父路径名字符串和子路径名字符串创建文件对象 |
public File(File parent, String child) | 根据父路径对应文件对象和子路径名字符串创建文件对象 |
注意
- File对象可以定位文件和文件夹
- File封装的对象仅仅是一个路径名,这个路径可以是存在的,也可以是不存在的。
package com.itheima.d1_file1;
import java.io.File;
public class FileDemo {
public static void main(String[] args) {
// 创建File对象 (指定了文件的路径)
// 路径的写法:
// D:/to/path/file
// D:\\to\\path\\file
File f = new File("");
long size = f.length(); // 文件字节大小
System.out.println(size);
// 1.创建File对象, 支持绝对路径 支持相对路径(重点)
File f1 = new File("D:/云计算/图片/wallhaven-3kkkr9.png");
System.out.println(f1.length());
// 2.相对路径: 一般定位模块中的文件 找到相对的工程下
File f2 = new File("file-io-app/src/data.txt");
System.out.println(f2.length());
// 3.File创建对象,可以是文件也可以是文件夹
File f3 = new File("E:\\resources");
System.out.println(f3.exists());
}
}
运行结果:
0
1104604
6
true
总结:
1、File类的作用?
- 创建对象定位文件,可以删除、获取文件信息等。但是不能读写文件内容。
2、File类构建对象的方式 ?
- File file = new File(“文件/文件夹/绝对路径/相对路径”);
3、绝对路径和相对路径是什么样的?
- 绝对路径是带盘符的。
- 相对路径是不带盘符的,默认到当前工程下寻找文件。
# 判断文件类型、获取信息
File类的判断文件类型、获取文件信息功能
方法名称 | 说明 |
---|---|
public boolean isDirectory() | 判断此路径名表示的File是否为文件夹 |
public boolean isFile() | 判断此路径名表示的File是否为文件 |
public boolean exists() | 判断此路径名表示的File是否存在 |
public long length() | 返回文件的大小(字节数量) |
public String getAbsolutePath() | 返回文件的绝对路径 |
public String getPath() | 返回定义文件时使用的路径 |
public String getName() | 返回文件的名称,带后缀 |
public long lastModified() | 返回文件的最后修改时间(时间毫秒值) |
package com.itheima.d1_file1;
import java.io.File;
import java.text.SimpleDateFormat;
/*目标:File类的获取功能的API
- public String getAbsolutePath() 返回File的绝对路径名字字符串
- public String getPath() 获取创建文件对象的时候用的路径
- public String getName() 返回由此File标识的文件或目录的名称
- public long length() 返回由此File表示的文件长度
*/
public class FileDemo1 {
public static void main(String[] args) {
// 1.绝对路径创建一个文件对象
File f1 = new File("E:\\resources\\161605.png");
// 获取它的绝对路径
System.out.println(f1.getAbsoluteFile());
// 获取文件定义的时候使用的路径
System.out.println(f1.getPath());
// 获取文件的名称: 带后缀
System.out.println(f1.getName());
// 获取文件的大下: 字节个数
System.out.println(f1.length());
// 获取文件的最后修改时间
long time = f1.lastModified();
System.out.println("最后修改时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time));
// 判断文件还是文件夹
System.out.println(f1.isFile()); // true
System.out.println(f1.isDirectory()); // false
System.out.println("----------------------------");
// 2.相对路径创建一个文件对象
File f2 = new File("file-io-app/src/data.txt");
// 获取它的绝对路径
System.out.println(f2.getAbsoluteFile());
// 获取文件定义的时候使用的路径
System.out.println(f2.getPath());
// 获取文件的名称: 带后缀
System.out.println(f2.getName());
// 获取文件的大下: 字节个数
System.out.println(f2.length());
// 获取文件的最后修改时间
long time1 = f2.lastModified();
System.out.println("最后修改时间:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(time1));
// 判断文件还是文件夹
System.out.println(f2.isFile()); // true
System.out.println(f2.isDirectory()); // false
}
}
运行结果:
false
true
false
true
true
true
# 创建、删除文件功能
File类创建文件的功能
方法名称 | 说明 |
---|---|
public boolean createNewFile() | 创建一个新的空的文件 |
public boolean mkdir() | 只能创建一级文件夹 |
public boolean mkdirs() | 可以创建多级文件夹 |
File类删除文件的功能
方法名称 | 说明 |
---|---|
public boolean delete() | 删除由此抽象路径名表示的文件或空文件夹 |
注意
delete方法默认只能删除文件和空文件夹,delete方法直接删除不走回收站
package com.itheima.d1_file1;
import java.io.File;
import java.io.IOException;
/*
目标: File类的创建和删除的方法
- public boolean createNewFile() 当且仅有该名称的文件尚不存在时,创建一个文件
- public boolean delete() 删除此File标识的文件或者目录 (只能删除空目录)
- public boolean mkdir() 创建由此File表示的目录 (只能创建一级目录)
- public boolean mkdirs() 创建多个目录(建议使用)
*/
public class FileDemo2 {
public static void main(String[] args) throws IOException {
File f = new File("file-io-app\\src\\data.txt");
// 创建文件 创建成功返回true反之不需要这个,以后文件写出去的时候会自动创建
System.out.println(f.createNewFile());
File f1 = new File("file-io-app\\src\\data02.txt");
System.out.println(f1.createNewFile());
// mkdir 创建一个一级目录
File f2 = new File("D:/resources/aaa");
System.out.println(f2.mkdir());
// mkdirs创建多级目录
File f3 = new File("D:/resources/aaa/bbb/ccc/ddd");
System.out.println(f3.mkdirs());
// 删除文件或者空文件夹 (删除不了非空)
System.out.println(f1.delete());
System.out.println(f3.delete());
}
}
运行结果:
false
true
false
true
true
true
总结:
1.创建多级目录使用哪个方法?
- public boolean mkdirs()
2.删除文件需要注意什么?
- 可以删除文件、空文件夹。
- 默认不能删除非空文件夹。
# 遍历文件夹
File类的遍历功能
方法名称 | 说明 |
---|---|
public String[] list() | 获取当前目录下所有的"一级文件名称"到一个字符串数组中去返回。 |
public File[] listFiles()(常用) | 获取当前目录下所有的"一级文件对象"到一个文件对象数组中去返回(重点) |
listFiles方法注意事项:
- 当文件不存在时或者代表文件时,返回null
- 当文件对象代表一个空文件夹时,返回一个长度为0的数组
- 当文件对象是一个有内容的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回
- 当文件对象是一个有隐藏文件的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏文件
- 当没有权限访问该文件夹时,返回null
package com.itheima.d1_file1;
import java.io.File;
/*
目标: File针对目录的遍历
- public String[] list()
获取当前目录下的所有的一级文件夹或者一级文件到字符串数组中去返回
- public File[] listFiles() (常用)
获取当前目录下所有的一级文件对象到一个文件对象数组中去返回 (重点)
*/
public class FileDemo3 {
public static void main(String[] args) {
File f1 = new File("D:/resources/");
String[] names = f1.list();
for (String name : names) {
System.out.println(name);
}
// 一级文件对象
// 获取当前目录下所有的一级文件对象 到 一个文件对象数组中去返回
File[] files = f1.listFiles();
for (File file : files) {
System.out.println(file);
}
// 注意事项:
File dir = new File("D:/aaaaaa");
File[] files1 = dir.listFiles();
System.out.println(files1);
}
}
运行结果:
aaa
aaa.txt
bbb.txt
ccc.txt
D:\resources\aaa
D:\resources\aaa.txt
D:\resources\bbb.txt
D:\resources\ccc.txt
null
总结:
1.如何遍历文件夹下的文件对象,使用哪个API,有什么特点?
- public File[] listFiles()(常用)。
- 只能遍历当前文件夹对象下的一级文件对象。
# 方法递归
# 方法递归概述
什么是方法递归?
- 递归做为一种算法 (opens new window)在程序设计语言 (opens new window)中广泛应用。
- 方法调用自身的形式称为方法递归( recursion)。
递归的形式
- 直接递归:方法自己调用自己。
- 间接递归:方法调用其他方法,其他方法又回调方法自己。
方法递归存在的问题?
- 递归如果没有控制好终止,会出现递归死循环,导致栈内存溢出现象。
1.什么是递归?
- 方法调用自己的形式称为方法递归( recursion)。
2.什么是递归死循环?
- 方法无限调用自己,无法终止,最终引起栈内存溢出。
# 计算1-n的阶乘
需求:计算1-n的阶乘的结果,使用递归思想解决,我们先从数学思维上理解递归的应用和核心点。
分析
①假如我们认为存在一个公式是 f(n) = 1234567*…(n-1)*n;
②那么公式等价形式就是: f(n) = f(n-1) *n
③如果求的是 1-5的阶乘 的结果,我们手工应该应该如何应用上述公式计算。
④f(5) = f(4) * 5 f(4) = f(3) * 4 f(3) = f(2) * 3 f(2) = f(1) * 2 f(1) = 1
package com.itheima.d1_file1.d2_file;
public class Filedemo1 {
public static void main(String[] args) {
System.out.println(f(5));
}
public static int f(int n){
if (n == 1){
return 1;
}else {
return n * f(n -1);
}
}
}
运行结果:
120
递归算法三要素大体可以总结为:
- 递归的公式: f(n) = f(n-1) * n;
- 递归的终结点:f(1)
- 递归的方向必须走向终结点:
# 文件搜索案例
需求:文件搜索、从C:盘中,搜索出某个文件名称并输出绝对路径。
分析:
①先定位出的应该是一级文件对象
②遍历全部一级文件对象,判断是否是文件
③如果是文件,判断是否是自己想要的
④如果是文件夹,需要继续递归进去重复上述过程
package com.itheima.d1_file1.d2_file;
import java.io.File;
import java.io.IOException;
public class FileDemo2 {
public static void main(String[] args) {
searchFile(new File("D:/"),"WeChat.exe");
}
public static void searchFile(File dir,String name){
// 判断dir是否是目录
if (dir != null && dir.isDirectory()){
// 可以找
// 提取当前的目录
File[] files = dir.listFiles();
// 判断是否存在一级文件对象
if (files != null && files.length > 0){
for (File file : files) {
// 判断当前遍历的一级文件对象还是目录
if (file.isFile()){
// 是不是要找的, 是就把其路径输出即可
if (file.getName().contains(name)){
System.out.println("找到了" + file.getAbsolutePath());
try {
Runtime r = Runtime.getRuntime();
r.exec(file.getAbsolutePath());
} catch (IOException e) {
e.printStackTrace();
}
}
}else {
// 是文件夹 需要继续递归
searchFile(file,name);
}
}
}
}else {
System.out.println("当前的路径不是目录!");
}
}
}
运行结果:
找到了D:\软件\WeChat\WeChat.exe
找到了D:\软件\WeChat\[3.7.0.30]\WeChat.exe
# 啤酒兑奖案例
需求:
啤酒2元1瓶,4个盖子可以换一瓶,2个空瓶可以换一瓶,
请问10元钱可以喝多少瓶酒,剩余多少空瓶和盖子。
答案:
15瓶 3盖子 1瓶子
package com.itheima.d1_file1.d2_file;
public class FileDemo3 {
public static int totalNumber;
public static int lastCoverNumber;
public static int lastBottleNumber;
public static void main(String[] args) {
buy(10);
System.out.println(totalNumber);
System.out.println(lastCoverNumber);
System.out.println(lastBottleNumber);
}
private static void buy(int money) {
// 这里是计算啤酒总数
int number = money / 2;
totalNumber += number;
// 分别有5个瓶盖和5个瓶子
int CoverNumber = lastCoverNumber + number;
int BottleNumber = lastBottleNumber + number;
// 计算额外的钱 (瓶盖和瓶子可以当钱)
int allMoney = 0;
if (CoverNumber >= 4){
allMoney += (CoverNumber /4) * 2;
}
lastCoverNumber = CoverNumber % 4;
if(BottleNumber >= 2){
allMoney += (BottleNumber /2) * 2;
}
lastBottleNumber = BottleNumber % 2;
// 最后判断大于2的钱继续兑换
if (allMoney >= 2){
buy(allMoney);
}
}
}
运行结果:
总钱totalNumber15
3
1
# IO流
# IO流概述
I表示intput
,把硬盘文件中的数据读入到内存的过程,称之输入,负责读。
O表示output
,把内存中的数据写出到硬盘文件的过程,称之输出,负责写。
# IO流的分类
# 总结流的四大类
字节输入流
:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存
中去的流称为字节输入流。字节输出流
:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去
的流称为字节输出流。字符输入流
:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存
中去的流称为字符输入流。字符输出流
:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中
去的流称为字符输出流。
1.IO流的作用?
- 读写文件数据的
2.IO流是怎么划分的,大体分为几类,各自的作用?
- 字节输入流 InputStream(读字节数据的)
- 字节输出流 OutoutStream(写字节数据出去的)
- 字符输入流 Reader(读字符数据的)
- 字符输出流 Writer(写字符数据出去的)
# 字节输入流
文件字节输入流:FileInputStream
作用:以内存为基准,把磁盘文件中的数据以字节的形式读取到内存中去。
构造器 | 说明 |
---|---|
public FileInputStream(File file) | 创建字节输入流管道与源文件对象接通 |
public FileInputStream(String pathname) | 创建字节输入流管道与源文件路径接通 |
方法名称 | 说明 |
---|---|
public int read() | 每次读取一个字节返回,如果字节已经没有可读的返回-1 |
public int read(byte[] buffer) | 每次读取一个字节数组返回,如果字节已经没有可读的返回-1 |
注意:
在src下面创建data.txt,随便输入。
# 每次读取一个字节
package com.itheima.d1_demo1;
import java.io.FileInputStream;
import java.io.InputStream;
public class FileInputStreamDemo1 {
public static void main(String[] args) throws Exception {
// 创建一个文件字节输入流管道与文件接通
// InputStream is = new FileInputStream(new File("logback-app\\src\\data.txt"));
// 简化写法
InputStream is = new FileInputStream("file-io-app\\src\\data.txt");
// 读取一个字节返回
int b1 = is.read();
System.out.println(b1);
int b2 = is.read();
System.out.println(b2);
int b3 = is.read();
System.out.println((char)b3);
int b4 = is.read();
System.out.println(b4);
// 使用循环改进
// 定义一个变量记录每次读取的字节
int b;
while ((b = is.read()) != -1){
System.out.println((char) b);
}
}
}
运行结果:
97
98
3
97
总结:
1.文件字节输入流,每次读取一个字节的api是哪个?
方法名称 | 说明 |
---|---|
public int read() | 每次读取一个字节返回,如果字节已经没有可读的返回-1 |
2.每次读取一个字节存在什么问题?
- 性能较慢
- 读取中文字符输出无法避免乱码问题。
# 每次读取一个字节数组
文件字节输入流:FileInputStream
作用:以内存为基准,把磁盘文件中的数据以字节的形式读取到内存中去。
方法名称 | 说明 |
---|---|
public int read() | 每次读取一个字节返回,如果字节已经没有可读的返回-1 |
public int read(byte[] buffer) | 每次使用字节数组来读取数据,返回读取的字节个数,如果没有可读返回-1 |
package com.itheima.d1_demo1;
import java.io.FileInputStream;
import java.io.InputStream;
public class FileInputStreamDemo2 {
public static void main(String[] args) throws Exception {
// 创建一个文件字节输入流管道与文件接通
InputStream is = new FileInputStream("file-io-app/src/data.txt");
// 定义一个字节数组,用于读写字节数组
byte[] buffer = new byte[3];
int len = is.read(buffer);
System.out.println("读取了几个字节" + len);
String rs = new String(buffer);
System.out.println(rs);
int len1 = is.read(buffer);
System.out.println("读取了几个字节" + len1);
String rs1 = new String(buffer);
System.out.println(rs1);
// 读多少倒出多少
int len2 = is.read(buffer);
System.out.println("读取了几个字节" + len2);
String rs2 = new String(buffer,0,len2);
System.out.println(rs2);
// 改进循环,每次读取一个字节数组
/*
byte[] buffer = new byte[3];
int len; // 记录每次读取的字节数
while ((len = is.read(buffer)) != -1){
// 读取多少倒出多少
System.out.print(new String(buffer,0,len));
}
*/
}
}
运行结果:
读取了几个字节3
ab3
读取了几个字节3
ab�
读取了几个字节3
���
总结:
1.文件字节输入流,每次读取一个字节数组的api是哪个?
方法名称 | 说明 |
---|---|
public int read(byte[] buffer) | 每次读取一个字节数组返回,如果字节已经没有可读的返回-1 |
2.每次读取一个字节数组存在什么问题?
- 读取的性能得到了提升
- 读取中文字符输出无法避免乱码问题。
思考:
1、使用字节流读取中文输出乱码,如何使用字节输入流读取中文输出不乱码呢?
- 定义一个与文件一样大的字节数组,一次性读取完文件的全部字节。
2、直接把文件数据全部读取到一个字节数组可以避免乱码,是否存在问题?
- 如果文件过大,字节数组可能引起内存溢出。
# 读取文件的全部字节
方式一
自己定义一个字节数组与文件的大小一样大,然后使用读取字节数组的方法,一次性读取完成。
方法名称 | 说明 |
---|---|
public int read(byte[] buffer) | 每次读取一个字节数组返回,如果字节已经没有可读的返回-1 |
方式二
官方为字节输入流InputStream提供了如下API可以直接把文件的全部数据读取到一个字节数组中
方法名称 | 说明 |
---|---|
public byte[] readAllBytes() throws IOException | 直接将当前字节输入流对应的文件对象的字节数据装到一个字节数组返回 |
package com.itheima.d1_demo1;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
public class FileInputStreamDemo3 {
public static void main(String[] args) throws Exception {
File f = new File("file-io-app/src/data.txt");
InputStream is = new FileInputStream(f);
// 定义一个字节数组与文件的大小刚刚好一样大
byte[] buffer = new byte[(int) f.length()];
int len = is.read(buffer);
System.out.println("读取了多少个字节:" + len);
System.out.println("文件大小:" + f.length());
System.out.print(new String(buffer));
// byte[] buffer = is.readAllBytes();
// System.out.println(new String(buffer));
}
}
运行结果:
读取了多少个字节:22
文件大小:22
ab3ab我爱你中国ab
总结:
1.如何使用字节输入流读取中文内容输出不乱码呢?
- 一次性读取完全部字节。
- 可以定义与文件一样大的字节数组读取,也可以使用官方API.
2.直接把文件数据全部读取到一个字节数组可以避免乱码,是否存在问题?
- 如果文件过大,定义的字节数组可能引起内存溢出。
# 文件字节输出流
文件字节输出流:FileOutputStream
作用:以内存为基准,把内存中的数据以字节的形式写出到磁盘文件中去的流。
构造器 | 说明 |
---|---|
public FileOutputStream(File file) | 创建字节输出流管道与源文件对象接通 |
public FileOutputStream(File file,boolean append) | 创建字节输出流管道与源文件对象接通,可追加数据 |
public FileOutputStream(String filepath) | 创建字节输出流管道与源文件路径接通 |
public FileOutputStream(String filepath,boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
文件字节输出流(FileOutputStream)写数据出去的API
方法名称 | 说明 |
---|---|
public void write(int a) | 写一个字节出去 |
public void write(byte[] buffer) | 写一个字节数组出去 |
public void write(byte[] buffer , int pos , int len) | 写一个字节数组的一部分出去。 |
流的关闭与刷新
方法 | 说明 |
---|---|
flush() | 刷新流,还可以继续写数据 |
close() | 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据 |
package com.itheima.d1_demo1;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/*
换行: os.write("\r\n.getBytes()"); 换行
追加数据管道: OutputStream os = new FileOutputStream("file-io-app/data.txt",true); // 追加管道
*/
public class OutputStreamDemo1 {
public static void main(String[] args) throws IOException {
// 创建一个文件字节输出流管道与目标文件接通
OutputStream os = new FileOutputStream("file-io-app/src/test.txt");
// 写数据出去
// a.public void write(int a) 写一个字节出去
os.write('a');
os.write(98);
os.write("\r\n".getBytes());
os.write('徐');
// b.public void write(byte[] buffer) 写一个字节数组出去
byte[] buffer = {'a',97,98,99};
os.write(buffer);
byte[] buffer2 = "我是中国人".getBytes();
os.write("\r\n".getBytes());
os.write(buffer2);
// c.public void write(byte[] buffer, int pos,int len) 写一个字节数组的一部分出去
byte[] buffer3 = {'a',97,98,99};
os.write(buffer3,0,3);
os.write("\r\n".getBytes());
// 写数据必须刷新数据
// os.flush(); // 写数据时继续刷新,刷新数据 可以继续使用流
os.close(); // 释放资源,包含了刷新的,关闭后流不可以使用了
}
}
以下是test.txt的内容:
ab
�aabc
我是中国人aab
总结:
1.字节输出流写数据的方法有哪些
方法名称 | 说明 |
---|---|
public void write(int a) | 写一个字节出去 |
public void write(byte[] buffer) | 写一个字节数组出去 |
public void write(byte[] buffer , int pos , int len) | 写一个字节数组的一部分出去。 |
2.字节输出流如何实现数据追加
public FileOutputStream(String filepath,boolean append) | 创建字节输出流管道与源文件路径接通,可追加数据 |
---|
# 文件拷贝
需求:
- 把某个视频复制到其他目录下的“new.mp4”
思路:
①根据数据源创建字节输入流对象
②根据目的地创建字节输出流对象
③读写数据,复制视频
④释放资源
package com.itheima.d1_demo1;
import java.io.*;
/*
目标: 学会使用字节流完成文件的复制(支持一文件类型的复制)
*/
public class CopyDemo1 {
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
// 创建一个字节输入流管道与原视频对接
is = new FileInputStream("D:\\Devops\\01-Java学习介绍.mp4");
// 创建一个字节输出流管道与目标文件连通
os = new FileOutputStream("D:\\Devops\\new.mp4");
// 定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1){
os.write(buffer,0,len);
}
System.out.println("复制完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行结果:
复制完成
# 资源释放的方式
资源的释放方式有如下两种:
utry-catch-finally
utry-with-resource
# try-catch-finally
finally:放在try-catch后面的,无论是正常执行还是异常执行代码,最后一定要执行,除非JVM退出。
作用:一般用于进行最后的资源释放操作(专业级做法)
try-catch-finally的作用
- finally代码块是最终一定要执行的,可以在代码执行完毕的最后用于释放资源。
try-catch-finally格式
try {
FileOutputStream fos = new FileOutputStream("a.txt");
fos.write(97);
} catch (IOException e) {
e.printStackTrace();
} finally{
}
继续使用以上案例进行优化:
package com.itheima.d1_demo1;
import java.io.*;
/*
目标: 学会使用字节流完成文件的复制(支持一文件类型的复制)
*/
public class CopyDemo1 {
public static void main(String[] args) {
InputStream is = null;
OutputStream os = null;
try {
// 创建一个字节输入流管道与原视频对接
is = new FileInputStream("D:\\Devops\\01-Java学习介绍.mp4");
// 创建一个字节输出流管道与目标文件连通
os = new FileOutputStream("D:\\Devops\\new.mp4");
// 定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1){
os.write(buffer,0,len);
}
System.out.println("复制完成");
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println("=====finally=====");
// 关闭流
try {
if (os!=null)os.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
if (is!=null)is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
# try-with-resource
注意事项:
- JDK 7 以及 JDK 9的()中只能放置资源对象,否则报错
- 什么是资源呢?
- 资源都是实现了Closeable/AutoCloseable接口的类对象
public abstract class InputStream implements Closeable {}
public abstract class OutputStream implements Closeable, Flushable{}
继续使用上面示例优化:
package com.itheima.d1_demo1;
import java.io.*;
public class CopyDemo3 {
public static void main(String[] args) throws Exception {
// 创建一个字节输入流管道与原视频对接
InputStream is = new FileInputStream("D:\\Devops\\01-Java学习介绍.mp4");
// 创建一个字节输出流管道与目标文件连通
OutputStream os = new FileOutputStream("D:\\Devops\\new.mp4");
try (is;os){
// 定义一个字节数组转移数据
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
System.out.println("复制完成");
} catch (Exception e) {
e.printStackTrace();
}
}
}