文章目录
- 一、文件的概念
- 二、路径
- 三、文件的种类
- 四、JAVA中操作文件
-
- [4.1 File类](#4.1 File类)
-
- [1. 属性表格](#1. 属性表格)
- [2. 构造方法表格](#2. 构造方法表格)
- [3. 方法表格](#3. 方法表格)
- 4.2方法的使用
- 五、文件内容操作
-
- 5.1流的分类
- [5.2 InputStream概述](#5.2 InputStream概述)
- [5.3 OutputStream概述](#5.3 OutputStream概述)
- 5.4Reader的使用
- 5.5Writer的使用
一、文件的概念
狭义的文件 :保存在硬盘上的文件。
广义的文件:操作系统进行管理的一种机制,很多软件/硬件资源抽象成"文件"来进行表示。
注:当前这篇文章主要讨论狭义文件。
下面这张图片里面有一些文件,在计算机专业术语中称做:目录

一台计算机中能保存很多文件,区分/识别一个文件就需要通过文件的路径来进行识别。
二、路径
路径: 定位到文件的一系列过程。在计算机中目录套目录,形成了树形结构,从树根开始,到最终的文件,都需要经过哪些目录,把这些目录记录下来,就构成了路径。
斜杠 / : 在主流的操作系统中都是使用/来分割的。但是Windows是例外,Windows / 和 \(反斜杠 ) 都支持(Windows默认使用\)
2.1绝对路径
从根节点开始,逐级表示出来
示例:找E盘LX2下的test.txt文件的路径

绝对路为: E:\前端开发\实验二\LX2\test.txt
2.2相对路径
需要明确一个基准路径,以这个基准来找对应的文件。
示例:找E盘LX2下的test.txt文件的相对路径

假设基准为:E:\前端开发\实验二\LX2,那么test.txt的相对路径就是:./test.txt (.表示当前所在的目录位置)
假设基准为:E:\前端开发\实验二,那么test.txt的相对路径就是:./LX2/test.txt
假设基准为:E:\前端开发\实验二\LX2\photo,那么test.txt的相对路径就是:.../test.txt(..表示当前路径的上一层路径)
如果在代码中写一个相对路径,基准路径是谁呢?
不确定,取决于程序的运行方式,在IDEA中直接运行,基准路径就是项目的目录,如果打一个jar包,单独运行jar包,当前在哪个目录下执行运行命令(java -jar jar包名),基准目录就是哪个目录。
三、文件的种类
从开发的角度把文件分为两大类
- 1.文本文件
- 2.二进制文件
在实际开发中判断一个文件是否是文本,最简单的方法是用记事本打开,打开之后不是乱码,能看懂文本,就是文本文件,如果是乱码,看不懂,就是二进制文件。
示例:二进制文件 图片,音频,视频,可执行程序,word,docx 都是典型的二进制文件。
示例:文本文件 txt纯文本, .java, .c都是典型的文本文件。
四、JAVA中操作文件
Java中通过java.io.File 类来对⼀个⽂件(包括目录)进行抽象的描述。注意,有File对象,并不代表真实存在该文件。
4.1 File类
File类是 Java 标准库(java.io 包)中定义的一个类。它用来表示文件或目录的路径,并提供操作这些路径的方法。
1. 属性表格
| 修饰符及类型 | 属性 | 说明 |
|---|---|---|
static String |
pathSeparator |
依赖于系统的路径分隔符,String 类型的表示 |
static char |
pathSeparator |
依赖于系统的路径分隔符,char 类型的表示 |
参数String文件的路径使用绝对路径/相对路径均可。
2. 构造方法表格
| 签名 | 说明 |
|---|---|
File(File parent, String child) |
根据父目录 + 孩子文件路径,创建一个新的 File 实例 |
File(String pathname) |
根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径 |
File(String parent, String child) |
根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示 |
3. 方法表格
| 修饰符及返回值类型 | 方法签名 | 说明 |
|---|---|---|
String |
getParent() |
返回 File 对象的父目录文件路径 |
String |
getName() |
返回 File 对象的纯文件名称 |
String |
getPath() |
返回 File 对象的文件路径 |
String |
getAbsolutePath() |
返回 File 对象的绝对路径 |
String |
getCanonicalPath() |
返回 File 对象的修饰过的绝对路径 |
boolean |
exists() |
判断 File 对象描述的文件是否真实存在 |
boolean |
isDirectory() |
判断 File 对象代表的文件是否是一个目录 |
boolean |
isFile() |
判断 File 对象代表的文件是否是一个普通文件 |
boolean |
createNewFile() |
根据 File 对象,自动创建一个空文件。成功创建后返回 true |
boolean |
delete() |
根据 File 对象,删除该文件。成功删除后返回 true |
void |
deleteOnExit() |
根据 File 对象,标注文件将被删除,删除动作会到 JVM 运行结束时才会进行 |
String[] |
list() |
返回 File 对象代表的目录下的所有文件名 |
File[] |
listFiles() |
返回 File 对象代表的目录下的所有文件,以 File 对象表示 |
boolean |
mkdir() |
创建 File 对象代表的目录 |
boolean |
mkdirs() |
创建 File 对象代表的目录,如果必要,会创建中间目录 |
boolean |
renameTo(File dest) |
进行文件改名,也可以视为我们平时的剪切、粘贴操作 |
boolean |
canRead() |
判断用户是否对文件有可读权限 |
boolean |
canWrite() |
判断用户是否对文件有可写权限 |
4.2方法的使用
1.得到文件的基本信息操作
java
package demo1;
import java.io.File;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
// 此处传入的是绝对路径,getPath得到的就是绝对路径
File file = new File("E:/前端开发/实验二/LX2/test.txt");
System.out.println("父目录文件路径: "+file.getParent());
System.out.println("文件名称: "+file.getName());
System.out.println("文件路径"+file.getPath());
System.out.println("文件的绝对路径"+file.getAbsolutePath());
// 简化了绝对路径中的 . 和 ..
System.out.println("简化过后的绝对路径"+file.getCanonicalFile());
}
}
打印结果:

2.显示目录下的文件操作
java
import java.io.File;
import java.util.Arrays;
public class Test {
public static void main(String[] args) {
File file = new File("E:/");
//list 只是列出当前目录的子元素,无法列出子目录中的具体内容
String[] list = file.list();
System.out.println(Arrays.toString(list));
System.out.println("================");
// File 对象代表的目录下的所有文件,以 File 对象表示
File[] list2 = file.listFiles();
System.out.println(Arrays.toString(list2));
}
}
打印结果:

3.创建目录
当前文件夹下为空,我们可以通过mkdir()创建目录

java
public class Test {
public static void main(String[] args) {
File file = new File("E:/新建文件夹/text");
System.out.println(file.mkdir());
}
}
打印结果:

可以发现刚刚的文件夹下新建了一个名为text的目录

4.总结
1.文件是存储在硬盘上的。
2.目录也是文件,操作系统通过树形结构组织目录和文件的
3.通过路径定位到具体的文件
4.文件分为:文本文件和二进制文件
五、文件内容操作
JAVA中针对文件内容的操作,主要是通过一组流来实现的。
计算机中的流和水流非常相似:把数据看作连续不断的字节序列,就像水管里流动的水。
水流的特点:你可以用一桶接满(一次取100升),也可以用两个50升的桶分两次接,或者用10个10升的桶......总之,只要最终总量是100升,取水方式可以任意拆分。
文件流同理:计算机把文件内容视为一段连续字节流(byte stream)。读取时,你可以一次 read(100) 全读完,也可以循环10次、每次 read(10),甚至一次读1字节、读100次。只要每次读的大小之和等于100,并且按顺序读取,都能正确拿到全部数据。
因此,计算机中针对读写文件,也是使用流(Stream)。
5.1流的分类
流有几十种,可以分为两个类别:
- 1.字节流:
读写文件以字节为单位,是针对二进制文件使用的
InputStream 输入 从文件读数据
OutputStream 输出 往文件写数据
- 2.字符流:
读写文件以字符为单位,是针对文本文件使用的
Reader 输入
Writer 输出
输入输出是什么意思?
看数据的流向,从硬盘到CPU (输入),从CPU到硬盘(输出)
5.2 InputStream概述
1.方法
| 修饰符及返回值类型 | 方法签名 | 说明 |
|---|---|---|
| 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() | 关闭字节流 |

2.使用
三个步骤:
1.打开文件
读
关闭
先创建一个名字为:text.txt的文件,内容为hello

java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) throws IOException {
// InputStream是抽象类,不能直接new
// 创建对象成功就相当于去打开文件
// try with resources 只要出现try代码块就会自动调用close
try(InputStream inputStream = new FileInputStream("./text.txt")){
while (true){
int i = inputStream.read();
if(i ==-1){
break;
}
System.out.println(i);
}
}
}
}
打印结果:hello这几个字母对应的ASCII表中的值

把text.txt中的文本内容改成:你好

如果文件中包含 非 ASCII 字符(如中文 "你"、"好"、表情符号等),这些字符在 UTF-8 编码下通常占多字节
一次读一个字节:
java
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class Test {
public static void main(String[] args) throws IOException {
// InputStream是抽象类,不能直接new
// 创建对象成功就相当于去打开文件
// try with resources 只要出现try代码块就会自动调用close
try(InputStream inputStream = new FileInputStream("./text.txt")){
while (true){
// 一次读一个字节
int i = inputStream.read();
if(i ==-1){
break;
}
// 这里打印十六进制 一个十六进制数字是4个比特位,两个十六进制数字就是1一个字节,所以选择用十六进制来进行打印核对
System.out.printf("%x\n",i);
}
}
}
}
打印结果:

发现和上面的你好的UTF-8的码表对应上了。
一次读多个字节
java
public class Test {
public static void main(String[] args) throws IOException {
try(InputStream inputStream = new FileInputStream("./text.txt")) {
//一次读多个字节 数组的长度自行定义
byte[] data = new byte[3];
// 此处的读操作尽可能让数组填满,
// 填不满的话,能填几个是几个
while (true){
// 此处的n是实际读到的字节数
int n = inputStream.read(data);
if(n == -1){
// 读完了
break;
}
for(int i = 0; i<n;i++){
System.out.printf("%x\n",data[i]);
}
System.out.println("===========");
}
}
}
}
打印结果:一次读三个字节

5.3 OutputStream概述
1.方法
| 修饰符及返回值类型 | 方法签名 | 说明 |
|---|---|---|
| void | write(int b) | 写入一个字节的数据 |
| void | write(byte[] b) | 将 b 这个字节数组中的数据全部写入输出流中 |
| void | write(byte[] b, int off, int len) | 将 b 这个字节数组中从 off 开始的数据写入输出流中,一共写 len 个 |
| void | close() | 关闭字节流 |
| void | flush() | 重要:我们知道 I/O 的速度是很慢的,所以,很多 OutputStream 为了减少设备操作的次数,在写数据的时候会先将数据暂时写入内存的一个指定区域里,直到该区域满了或者其他指定条件时才真正将数据写入设备中。这个区域一般称为缓冲区。但这会造成一个结果:我们写的数据很可能会遗留一部分在缓冲区中。需要在最后或者合适的位置调用 flush()(刷新)操作,将数据刷到设备中。 |

这里的参数是int,主要是因为希望参数的取值范围为:0~255,因为JAVA中没有unsiged类型。
2.使用
示例:在output.txt文本文件中写入abc
首先这里面没有output.txt文本文件,等下我们可以观察是否新建了一个output.txt文本文件并写入abc

通过代码来实现
java
import java.io.*;
public class Test {
public static void main(String[] args) {
try(OutputStream outputStream = new FileOutputStream("output.txt")){
outputStream.write(97);
outputStream.write(98);
outputStream.write(99);
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果:新建了一个output.txt文本文件并写入了abc

对于OutputStream来说,如果文件不存在,会尝试创建文件并写入
OutputStream是会清处上一次的内容,打开文件的一瞬间,就被清除了
示例:把刚刚的output.txt中的acb改为大写的ABC
java
import java.io.*;
public class Test {
public static void main(String[] args) {
try(OutputStream outputStream = new FileOutputStream("output.txt")){
byte[] bytes = {65,66,67};
outputStream.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行结果

5.4Reader的使用

示例:
把text.txt文件中的abc读出来
java
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class Test {
public static void main(String[] args) {
try(Reader reader = new FileReader("text.txt")){
while (true){
int n = reader.read();
if(n == -1){
break;
}
System.out.println((char ) n);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
打印结果

5.5Writer的使用
将writer.txt中写入hello world
java
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class Test {
public static void main(String[] args) {
try(Writer writer = new FileWriter("./writer.txt")){
writer.write("hello world");
} catch (IOException e) {
e.printStackTrace();
}
}
}
打印结果

在原来的hello world 的基础上再追加写hello world
javapublic
public static void main(String[] args) {
//追加再写一次hello world
try(Writer writer = new FileWriter("./writer.txt",true)){
writer.write("hello world ");
} catch (IOException e) {
e.printStackTrace();
}
}
}
打印结果


学习路上一起进步,如果觉得内容不错,记得点赞支持一下,也可以关注我,后续持续分享高质量技术文章!