目录
- 一、文件
- 1.1 文件的概念
- 1.2 文件的操作
- 1.3 路径
- 1.4 文件分类
- 二、Java中的文件元信息、路径操作
- 2.1 属性
- 2.2 构造方法
- 2.3 方法
- 2.3.1 文件路径
- 2.3.2 文件判断
- 2.3.3 文件创建删除
- 2.3.4 其他操作
- 三、文件读写操作
- 3.1 流(Stream)
- 3.1.1 字节流
- 3.1.1.1 InputStream
- 3.1.1.2 OutputStream
- 3.1.2 字符流
- 3.1.2.1 Reader
- 3.1.2.2 Writer
- 3.2 字节流字符流转换
一、文件
1.1 文件的概念
在操作系统中会将“硬盘设备”和“软件资源”都抽象成文件。
在生活中提到的文件大多指硬盘的文件(像c盘里面的文件),就是硬盘上的数据抽象而成的。
1.2 文件的操作
在计算机上文件是由操作系统提供的“文件系统”来组织管理的,操作系统使用“目录”(也就是常说的文件夹)来管理文件的。目录是一种树形结构
1.3 路径
- 绝对路径:就是以C盘D盘(C: D:)这种盘符开头的路径。如"E:\植物大战僵尸"。
- 相对路径:此时需要先指定一个基准目录,然后看通过什么样的路径来到指定文件,这个路径就是相对路径,用点开头。此时用一个点表示当前目录,两个点表示当前目录上一级目录。
举例:
假如我们要找“E:\植物大战僵尸\pvzHE"目录下的"fonts"文件。
- 如果我们当前在“E:\植物大战僵尸\pvzHE"目录下,直接使用“.\fonts”
- 如果我们在“E:\植物大战僵尸”目录下,使用“.\pvzHE\fonts”
- 如果我们在"E:\植物大战僵尸\pvzHE\新建文件夹"目录下,使用“…\fonts”
不同场景下的基准目录:
- 在命令行操作,当前目录就是基准目录。
- 在idea操作项目目录就是基准目录。
- 在图形化工具上就要看实际情况了。
1.4 文件分类
在编程角度上将文件分为两类:
- 文本文件:文件中保存的都是字符串,保存的都是合法的字符(合法的字符就是符合当前字符集编码的字符)。
- 二进制文件:文件中保存的仅仅是二进制数据。
二、Java中的文件元信息、路径操作
Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。
2.1 属性
修饰符及类型 | 属性 | 说明 |
---|---|---|
static String | pathSeparator | 依赖于系统的路径分隔符,String 类型的表示 |
static char | pathSeparator | 依赖于系统的路径分隔符,char 类型的表示 |
2.2 构造方法
签名 | 说明 |
---|---|
File(File parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径 |
File(String parent, String child) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示 |
2.3 方法
2.3.1 文件路径
修饰符及返回值类型 | 方法签名 | 说明 |
---|---|---|
String | getParent() | 返回 File 对象的父目录文件路径 |
String | getName() | 返回 FIle 对象的纯文件名称 |
String | getPath() | 返回 File 对象的文件路径 |
String | getAbsolutePath() | 返回 File 对象的绝对路径 |
String | getCanonicalPath() | 返回 File 对象的修饰过的绝对路径 |
2.3.2 文件判断
修饰符及返回值类型 | 方法签名 | 说明 |
---|---|---|
boolean | exists() | 判断 File 对象描述的文件是否真实存在 |
boolean | isDirectory() | 判断 File 对象代表的文件是否是一个目录 |
boolean | isFile() | 判断 File 对象代表的文件是否是一个普通文件 |
boolean | canRead() | 判断用户是否对文件有可读权限 |
boolean | canWrite() | 判断用户是否对文件有可写权限 |
2.3.3 文件创建删除
修饰符及返回值类型 | 方法签名 | 说明 |
---|---|---|
boolean | createNewFile() | 根据 File 对象,自动创建一个空文件。成功创建后返回 true |
boolean | delete() | 根据 File 对象,删除该文件。成功删除后返回 true |
void | deleteOnExit() | 根据 File 对象,标注文件将被删除,删除动作会到JVM 运行结束时才会进行 |
2.3.4 其他操作
修饰符及返回值类型 | 方法签名 | 说明 |
---|---|---|
String[ ] | list() | 返回 File 对象代表的目录下的所有文件名 |
File[ ] | listFiles() | 返回 File 对象代表的目录下的所有文件,以 File 对象表示 |
boolean | mkdir() | 创建 File 对象代表的目录 |
boolean | mkdirs() | 创建 File 对象代表的目录,如果必要,会创建中间目录 |
boolean | renameTo(Filedest) | 进行文件改名,也可以视为我们平时的剪切、粘贴操作 |
三、文件读写操作
在Java中对文件的读写操作使用流对象(stream)
3.1 流(Stream)
在标准库中提供的文件读写操作的类有很多,但可以分为两类。
3.1.1 字节流
字节流对应着二进制文件,每次读写的最小单位都是字节(Byte)。
字节流提供了两个父类(InputStream)(OutputStream)来供继承。
3.1.1.1 InputStream
InputStream在源码中是一个抽象类,不能直接new对象。提供了一个子类FileInputStream。
类需要传文件路径,如果文件没找到还会抛出FileNotFoundException异常。
方法简介
返回值 | 方法签名 | 说明 |
---|---|---|
int | read() | 读取一个字节的数据,返回 -1 代表已经完全读完了 |
int | read(byte[ ] b) | 最多读取 b.length 字节的数据到 b 中,返回实际读到的数量;-1 代表以及读完了 |
int | read(byte[ ] b, int off, int len) | 最多读取 len - off 字节的数据到 b 中,放在从 off 开始,返回实际读到的数量;-1 代表以及读完了 |
void | close() | 关闭字节流 |
3.1.1.2 OutputStream
默认打开一个文件会先清空,要继续写不清空在创建对象时传入true作为第二个参数。
OutputStream在源码中是一个抽象类,不能直接new对象。提供了一个子类FileOutputStream。
类需要传文件路径,如果文件没找到还会抛出FileNotFoundException异常。
方法
返回值 | 方法签名 | 说明 |
---|---|---|
void | write(int b) | 写入要给字节的数据 |
void | write(byte[ ] b) | 将 b 这个字符数组中的数据全部写入 os 中 |
int | write(byte[ ] b, int off, int len) | 将 b 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个 |
void | close() | 关闭字节流 |
void | flush() | 重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。 |
3.1.2 字符流
字符流对应着文本文件,每次读写的最小单位是字符(根据当前字符集来,一个中文字符在utf8就是3字节,GBK就是两字节)。
字符流就相当于对字节流进行了一个封装,自动帮我们把字节流中相邻几个字节转换成字符。
字符流提供了两个父类(Reader)(Writer)来供继承。
3.1.2.1 Reader
Reader在源码中是一个抽象类,不能直接new对象。提供了一个子类FileReader。
FileReader类需要传文件路径,如果文件没找到还会抛出FileNotFoundException异常。
Reader中读取字符常用是read方法,都会抛出IOException异常,介绍常用3种。
返回值 | 分法签名 | 说明 |
---|---|---|
int | read() | 读取一个字符,读取到返回ASCII值或者字符集编码值,没读取到返回-1 |
int | read(char[ ] cbuf) | 读取多个字符,尽量将cbuf数组填满,返回读取到的字符个数,如果读完文件返回-1 |
int | read(char[ ] cbuf, int off, int len) | l最多读len-off个,从数组off下标开始储存,返回读到的个数,如果读完文件返回-1 |
返回值说明:
int作为返回值时,返回的是一个2字节表示的,这时因为在Java中char类型是Unicode编码,而String是由utf8编码(String的编码集可改)。
创建了一个Reader对象要释放:对象名.close();
主要释放的是文件描述符表(在进程介绍PCB的主要属性),文件描述符表里面主要用顺序表(数组)来储存,如果一直不释放,里面数组被占满就会发生内存泄露。
但是如果直接就这么写,那如果上面代码抛出异常,就执行不到close,改进方法:
- try-finally处理:
Reader reader = new FileReader("d:/test.txt");
try {
int n = reader.read();
} finally {
reader.close();
}
- try with resource
在定义对象时放入,出了try语句就会自动调用类实现的close方法(必须是实现了closeable接口的)。
try( Reader reader = new FileReader("d:/test.txt") ) {
int n = reader.read();
}
3.1.2.2 Writer
默认打开一个文件会先清空,要继续写不清空在创建对象时传入true作为第二个参数。
InputStream在源码中是一个抽象类,不能直接new对象。提供了一个子类FileInputStream。
类需要传文件路径,如果文件没找到还会抛出IOException异常。
方法
返回值 | 方法签名 | 说明 |
---|---|---|
void | write(int c) | 写入要给文件的数据 |
void | write(char[ ] cbuf) | 将 cbuf 这个字符数组中的数据全部写入 os 中 |
int | write(byte[ ] cbuf, int off, int len) | 将 cbuf 这个字符数组中从 off 开始的数据写入 os 中,一共写 len 个 |
void | write(String str) | 将 str 这个字符串中的数据全部写入 os 中 |
void | write(String str, int off, int len) | 将 str 这个字符串中的数据从 off 开始的数据写入 os 中,一共写 len 个 |
void | close() | 关闭字节流 |
void | flush() | 重要:我们知道 I/O 的速度是很慢的,所以,大多的 OutputStream 为了减少设备操作的次数,在写数据的时候都会将数据先暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中,这个区域一般称为缓冲区。但造成一个结果,就是我们写的数据,很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置,调用 flush(刷新)操作,将数据刷到设备中。 |
3.2 字节流字符流转换
使用Scanner工具类去读取文件中的字符。
try(InputStream inputStream = new FileInputStream("D:/test.txt")) {
Scanner scanner = new Scanner(inputStream);
String s = scanner.next();
}
使用PrintWriter工具类去写入文件中的字符。
try(OutputStream outputStream = new FileOutputStream("D:/test.txt",true)) {
PrintWriter printWriter = new PrintWriter(outputStream);
printWriter.println();
}