文件操作
顾名思义, 操作磁盘上的某⼀个⽂件或者某⼀个⽂件夹。 可以对他们进⾏创建、 删除、 移动、 属性获取、 属性设置等操作。 但是, 并不包含读取⽂件的内容、 拷⻉⽂件。
在Java中, 使⽤ java.io.File 类描述⼀个⽂件, 或者是⼀个⽂件夹。
IO流
什么是IO流
IO流: Input/Output Stream
流: 指的是⼀串流动的数据, 在数据在流中按照指定的⽅向进⾏流动。 实现数据的读取、写⼊的功能。
**作⽤:**实现两个设备之间数据的传递
IO流的使⽤场景
使⽤File类, 只能做关于⽂件的操作, 获取属性、 创建⽂件、 删除⽂件、 移动⽂件等操作, 但是不包含读取⽂件中的内容。 如果需要读取、修改⽂件中的内容, 此时就需要使用IO流来完成了。
使⽤场景: 对某⼀个⽂件进⾏读取或者写⼊操作。
注意事项:
IO流是对⼀个⽂件进⾏读写的, 不是⼀个⽂件夹! 在使⽤IO流的时候, 不要建⽴与⼀个⽂件夹的连接。
设备
设备概念:能输出或者输⼊数据的都可以成为设备
设备:磁盘(硬盘),内存,键盘,⽂件,⽹络,控制台
⽹络:当前主机之外的⽹上资源
IO流的分类
按照不同的分类标准, 能够得到不同分类的IO流:
按照传输数据的单位:
字节流: 传输的是字节,是以字节为单位的。可以操作任意类型的数据 ------⾳频,视频,⽂件,图⽚等
字符流: 传输的是字节,不同点是在传输过程中加⼊了编码的操作,让我们的操作更⽅便------⽂本
按照数据传输的⽅向:
以内存为参考
输⼊流: 数据从其他设备传到内存
输出流: 数据从内存传到其他设备
基础的IO流类的简介
其实在 java.io 包中, 有很多很多的类, 都是来描述IO流的。 但是基本上所有的IO流的类, 都是直接或间接的继承⾃四⼤⽗类流。
字节流的两个⽗类:
字节输⼊流:InputStream
字节输出流:OutputStream
字符流的两个⽗类:
字符读⼊流:Reader
字符写出流:Writer
IO流使⽤的注意事项
四⼤⽗类流, 都是抽象类, 都不能实例化对象。 因此, 需要借助他们的⼦类实现数据的读写。
流对象⼀旦实例化完成, 将建⽴⼀个程序与⽂件之间的连接。 这个连接会持有
这个⽂件。 如果这个连接不断, 此时这个⽂件就是⼀个被使⽤中的状态, 此时将⽆法对这个⽂件进⾏其他的操作, 例如删除。
⼀个流在使⽤完成之后, 切记! ⼀定要进⾏流的关闭。
⽂件操作
绝对路径和相对路径
相关概念
路径: ⽤来描述⼀个⽂件所在的地址, ⽤来定位⼀个⽂件的。 可以分为绝对路径和相对路径。
绝对路径: 从磁盘的根⽬录开始, ⼀层层的向下查找, 直到找到这个⽂件。
相对路径: 找到⼀个参照物, 相对于这个参照物的路径。
对比
分隔符
分隔符的简介
在描述路径的字符串中, 有两种分隔符, 是⽐较常⻅的: ⽬录分隔符 和 路径分隔符。
⽬录分隔符
分隔开⼀个路径中的不同的⽂件夹, ⽤来描述层级关系、 包含关系。
在不同的操作系统中, ⽬录分隔符是不⼀样的。 在windows中, 使⽤ \ 作为⽬录分隔符; 在⾮windows的操作系统中, 例如: Linux、Unix… 使⽤的是 / 作为⽬录分隔符。
路径分隔符
分隔开⼀个字符串中的多个路径的。
在不同的操作系统中, 路径分隔符是不⼀样的。 在windows中, 使⽤ ; 作为路径分隔符; 在⾮windows的操作系统中, 例如: Linux、Unix… 使⽤的是 : 作为路径分隔符。
分隔符的表示
如果你的程序只需要考虑部署在windows平台, 那么只需要按照windows的规范书写就可以; 如果你的程序只需要部署到linux上, 那么只需要按照linux的规范书写就可以。 但是, 如果你的程序需要考虑在不同的平台上部署运⾏, 此时就需要使⽤以下⽅法进⾏分隔符的获取。
File类
File类的简介
File是 java.io 包中的⼀个类。 是对磁盘上的某⼀个⽂件、⽂件夹(⽬录)的描述。所谓的⽂件操作, 其实都是需要使⽤这个类来完成的。
File类的构造方法
File类的常⽤⽅法
- ⽂件属性获取⽅法
- ⽂件操作⽅法
3)子文件获取
基础的IO流
建⽴程序与⽂件的连接
其实, 就是建⽴了程序与⽂件之间连接的管道, 实现数据在这个管道之内进⾏流动。 管道分为不同的类型: 字节输⼊流、 字节输出流、 字符输⼊流、 字符输出流。 下⾯以字节输⼊InputStream 为例。
标准流程
try结构外⾯, 声明流对象, 为了在finally中使⽤。
在try结构⾥⾯, 实例化流对象, 并捕获异常。
在finally结构中, 对流进⾏关闭。 在关闭的时候, 需要考虑流对象是否是null, 以及要处理 IOException 异常。
try结构的特殊使⽤
在 JDK1.7 之后, 可以在try后⾯添加⼀对⼩括号。 将AutoClosable 接⼝实现类的对象, 实例化放到⼩括号中完成。 此时, 在try结构执⾏结束的时候, 会⾃动的调⽤AutoClosable接⼝实现类中的close⽅法, 进⾏流的关闭。 这样写的流的建⽴⽐较简
单, 也是后⾯我们最主要使⽤的⽅式。
try (InputStream inputStream = new
FileInputStream("file\\day25\\source")) {
// 数据的读取操作
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(new
File("file\\day25\\source").delete());
}
InputStream
InputStream简介
这是⼀个字节输⼊流。 从⽅向来说, 是⼀个输⼊流, 数据是从⽂件中流动到程序中(数据从其他设备到内存), 是为了读取⽂件中的数据的。 从数据单位来说, 这个流中流动的数据直接是字节的形式。
⽂件的读取
注意:
1.为了⽅便测试,我们可以先通过字节输出流或者⼿动在当前⼯程中创建⼀个test1.txt⽂件,写⼊字符串abcde
2.有三种读取数据的⽅式第⼀:⼀次读取⼀个字节;第⼆:⼀次读取多个字节;第三:⼀次读取全部字节
三种读取数据的⽅式中,推荐使⽤第⼆种,⼀次读取多个字节
- ⼀次读取⼀个字节
read():⼀个字节⼀个字节的读,每次读出⼀个字节
while ((num = inputStream.read()) != -1) {
System.out.print((char)num);
}
- ⼀次读取多个字节
read(数组):⼀次可以读出多个字节,数组的作⽤:每次会将读出的字节临时放到这个数组中
while ((num = inputStream.read(arr)) != -1){
System.out.println(new String(arr,0,num)+"
num:"+num);
}
- ⼀次读取全部字节
可以通过available()⽅法获取全部字节个数
// 1. 建⽴程序与⽂件之间的连接,⽤来读取这个⽂件
try (InputStream inputStream = new
FileInputStream("test1.txt")) {
// 2. 读取字节流中的数据,需要有⼀个字节数组,⽤来读取数据
//获取⽂件的字节个数
//注意:这种⽅式适合⽂件的字节数⽐较⼩的时候,⼤概是⼏kb之内.
int num = inputStream.available();
//2.读
byte[] bytes = new byte[num];
inputStream.read(bytes);
System.out.println(new String(bytes));
} catch (IOException e) {
e.printStackTrace();
}
OutputStream
OutputStream简介
字节输出流。 从⽅向上来分, 是⼀个输出流, 数据从程序中流动到⽂件中(数据从内存到其他设备), 实现⽂件的写操作。 从流中流动的数据单位来分, 是⼀个字节流,流中流动的数据直接是字节的形式。
⽂件的写
try (OutputStream outputStream = new
FileOutputStream("test1.txt",true)) {
// 2. 准备需要写⼊到这个⽂件中的数据
String message = "你好,师姐";
// 3. 将数据写⼊到输出流中,由输出流写⼊到⽂件中
//将字符串转成字节数组
outputStream.write(message.getBytes());
// 冲刷缓冲区,将缓冲区中的数据强制流动到⽂件中。
// 在流关闭的时候,会⾃动的调⽤。
//注意:当我们进⾏循环写⼊操作时,最好通过flush()⽅法刷新
outputStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
案例: ⽂件拷⻉
需求分析
实现, 将⼀个⽂件拷⻉到另外⼀个地⽅。 注意, 这个不是剪切, 拷⻉完成之后,原⽂件还在。
实现⽅式: 借助两个流来完成。
使⽤字节输⼊流输⼊, 循环读取原⽂件中的数据。
使⽤字节输出流, 将每次读取到的数据, 写⼊到⽬标⽂件中。
图示:
Reader
Reader的简介
这是⼀个字符输⼊流。 从⽅向来说, 是⼀个输⼊流, 数据是从⽂件中流动到程序中(数据从其他设备到内存), 是为了读取⽂件中的数据的。 从数据单位来说, 这个流中流动的数据以字节为单位的,不同的是在传输过程中加⼊了编码的操作,让我们的操作更⽅便。
try (Reader reader = new FileReader("file\\day25\\src"))
{
// 1. 实例化⼀个字符数组
char[] array = new char[100];
// 2. 声明⼀个变量,⽤来记录每次读取到了多少个数据
int length = 0;
// 3. 循环读取数据
while ((length = reader.read(array)) != -1) {
String str = new String(array, 0, length);
System.out.print(str);
}
}
catch (IOException e) {
e.printStackTrace();
}
Writer
Writer的简介
字符输出流。 从⽅向上来分, 是⼀个输出流, 数据从程序中流动到⽂件中(数据从内存到其他设备), 实现⽂件的写操作。 从流中流动的数据单位来分, 是⼀个字符流,流中流动的数据是以字节为单位,不同的是在传输过程中加⼊了编码的操作,让我们的操作更⽅便。
⽂件的写操作
try (Writer writer = new
FileWriter("file\\day25\\target", true)) {
// 2. 将数据写⼊到输出流中
writer.write("hello, world");
// 3. 冲刷缓冲区
writer.flush();
}
catch (IOException e) {
e.printStackTrace();
}
案例: ⽂件拷⻉
需求分析
实现, 将⼀个⽂件拷⻉到另外⼀个地⽅。 注意, 这个不是剪切, 拷⻉完成之后,原⽂件还在。
实现⽅式: 借助两个流来完成。
使⽤字符输⼊流, 循环读取原⽂件中的数据。
使⽤字符输出流, 将每次读取到的数据, 写⼊到⽬标⽂件中。
示例代码
private static void fileCopy2(String srcPath, String dstPath) {
// 2. 循环读取⽬标⽂件中的数据
try (Reader reader = new FileReader(srcPath); Writer writer= new FileWriter(dstPath)) {
// 3. 循环读取源⽂件中的数据
char[] array = new char[100];
int length = 0;
while ((length = reader.read(array)) != -1) {
// 4. 将读取到的数据写⼊到输出流
writer.write(array, 0, length);
}
writer.flush();
return true;
}
catch (IOException e) {
e.printStackTrace();
return false;
}
}
FileWriter(dstPath)) {
// 3. 循环读取源⽂件中的数据
char[] array = new char[100];
int length = 0;
while ((length = reader.read(array)) != -1) {
// 4. 将读取到的数据写⼊到输出流
writer.write(array, 0, length);
}
writer.flush();
return true;
}
catch (IOException e) {
e.printStackTrace();
return false;
}
}