文章目录
- 前言
- 一、文件是什么
- 1.文件的概念
- 2.文件路径
- 1.绝对路径
- 2.相对路径
- 二、针对文件的IO
- 1.File类
- 2.对文件内容的读写操作
- 1.针对文本文件—— 字符流
- 输入流 Reader类
- 输出流 Writer类
- 2.针对二进制文件—— 字节流
- 输入流 InputStream类
- 输出流 OutputStream类
- 总结
前言
本人是一个刚刚上路的IT新兵,菜鸟!分享一点自己的见解,如果有错误的地方欢迎各位大佬莅临指导,如果这篇文章可以帮助到你,劳请大家点赞转发支持一下!
本文与大家分享的是文件与文件路径,以及字符流与字节流,内容较为简单,容易理解吸收,各位加油!✨✨
一、文件是什么
1.文件的概念
✨我们先来认识什么是文件。
针对硬盘这种持久化存储的I/O设备,当我们想要 将数据保存到硬盘时 ,往往不是保存成一个整体,而是 独立成一个个的单位进行保存,这个独立的单位就被抽象成文件的概念 ,就类似书包里的一本本书一样真实存在。
上图中,C盘中的每个东西都是一个独立的文件。
文件除了有数据内容之外,还有一部分信息,例如文件名、文件类型、文件大小等并不作为文件的数据而存在,我们把这部分信息可以视为文件的元信息🪪。
2.文件路径
路径是指文件系统上一个文件/目录的具体位置 。
目录是计算机的专业术语,通俗的说法就是文件夹
🖥️计算机的目录是有层级结构的, 文件系统是以树形结构,N叉数来组织文件和目录的 。
此电脑(根结点)中有一个或多个盘符。
C盘里有这些文件夹
"music"中有三个文件夹。
"周杰伦"中有一首歌《晴天》
这大概是文件系统的一个树状图。
文件的路径,是通过一个字符串来表示, 每个目录之间使用 ‘/’ 或者 ‘\’ (只在Windows系统中适用, 代码中需要使用转义字符,因此需要写成’\\’ )来分割。
文件的路径非常重要,编程很多地方需要用到路径,尤其是相对路径
1.绝对路径
绝对路径:从根节点开始沿着树杈到达目标文件,中间经过的内容就是绝对路径 。
Windows系统都是从"此电脑"开始,表示路径时可以把"此电脑"省略直接从盘符开始
就比如这首歌《晴天》的绝对路径为:
“C:\music\周杰伦”。
2.相对路径
相对路径:从给定的某个目录(称之为基准目录/工作目录)查找到目标文件,中间经过的内容就是绝对路径 。
'.‘与’..'在相对路径中是两个个特殊符号,
'.‘表示当前目录,’..'表示上一级目录
- 相对路径的重中之重就是明确工作目录(基准目录) 😇😇😇
假设下图是我的工作目录,那么我要如何找到《晴天》呢??
此时的相对路径为:
“.\..\周杰伦”。
二、针对文件的IO
1.File类
IDEA的默认工作目录为:项目所在文件夹
java标准库中为我们提供了 File这个类来对一个文件(包括目录)进行抽象的描述 。
- 注意!!有 File 对象,并不代表该文件真实存在。
文件是存储在硬盘上的,直接通过代码操作不方便,因此就在内存中创建一个对应的对象,操作这个内存中的对象,就可以实现对硬盘中文件的操作。
可以理解为🤖遥控机器人,你使用代码遥控这个内存中的机器人,然后遥控机器人根据你的指令去操作文件。
File类的构造方法:
签名 | 说明 |
---|---|
File(File parent, Stringchild) | 根据父目录 + 孩子文件路径,创建一个新的 File 对象 |
File(String pathname) | 根据文件路径创建一个新的 File 实例,路径可以是绝对路径或者相对路径 |
File(String parent, Stringchild) | 根据父目录 + 孩子文件路径,创建一个新的 File 实例,父目录用路径表示 |
public static void main(String[] args) throws IOException {
// 使用绝对路径表示张杰这个文件夹中名为:"test.txt"的文件
File file = new File("C:/music/张杰/test.txt");
// 使用绝对路径表示张杰这个文件夹,这个File对象是一个文件夹/目录
File file1 = new File("C:/music/张杰");
//使用相对路径表示张杰这个文件夹中名为:"test.txt"的文件
File file2 = new File(file1,"test.txt");
File file3 = new File("C:/music/张杰","test.txt");
}
这个文件存在与否都可,但是路径不能错。
File类的常用方法:
修饰符及返回值类型 | 方法签名 | 说明 |
---|---|---|
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(Filedest) | 进行文件改名,也可以视为我们平时的剪切、粘贴操作 |
boolean | canRead() | 判断用户是否对文件有可读权限 |
boolean | canWrite() | 判断用户是否对文件有可写权限 |
演示一些方法。
public static void main(String[] args) throws IOException {
// 使用绝对路径在张杰这个文件夹中创建一个名为:"test.txt"的文件
File file = new File("C:/music/张杰/test.txt");
// 使用绝对路径表示张杰这个文件夹,这个File对象是一个文件夹/目录
File file1 = new File("C:/music/张杰");
//使用相对路径表示张杰这个文件夹中名为:"test.txt"的文件
File file2 = new File(file1,"test.txt");
File file3 = new File("C:/music/张杰","test.txt");
System.out.println("File 对象的父目录文件路径: " + file.getParent());
System.out.println("FIle 对象的纯文件名称: " + file.getName());
System.out.println("File 对象的文件路径: " + file.getPath());
System.out.println("File 对象的绝对路径: " + file.getAbsolutePath());
System.out.println("File 对象的修饰过的绝对路径: " + file.getCanonicalPath());
System.out.println("File 对象描述的文件是否真实存在: " + file.exists());
System.out.println("File 对象代表的文件是否是一个目录: " + file.isDirectory());
System.out.println("File 对象代表的文件是否是一个普通文件: " + file.isFile());
System.out.println("根据File 对象,自动创建一个空文件。成功创建后返回 true: " + file.createNewFile());
System.out.println("根据File 对象,删除该文件。成功删除后返回 true: " + file.delete());
File file4 = new File("C:/music/张杰/情歌");
System.out.println("在张杰文件夹中创建一个名为情歌的文件夹。成功创建后返回true: " + file4.mkdir());
File file5 = new File("C:/music/张杰/流行歌/2023年");
System.out.println("在张杰文件夹中创建一个创建多级目录。成功创建后返回true: " + file5.mkdirs());
}
运行结果:
2.对文件内容的读写操作
可以将文件的内容比作水库。
而对文件内容的读写就是从这个水库的排水口排水水🫗,从这个水库的进水口加水💧。
数据就像水流一样被读出来或者被写进去。
因此文件的读写也被称为 “数据流” 。
水流有大小,可以每次接取50ml,也可以接取100ml。
那么数据流肯定也可以控制读写的大小,一会为大家讲解。
而这个流的方向也与正常方向不太相同。
大家都知道CPU是计算机大脑的核心,所有操作都靠CPU完成,因此讨论输入输出都是以CPU为基准。
数据存储在硬盘上,数据在CPU上完成运算
因此
将数据从硬盘读入CPU中这个操作,称之为,输入流(将数据输入CPU) 。
将数据从CPU中写回硬盘这个操作,称之为,输出流(将数据输出到硬盘) 。
针对不同类型的文件又有不同的读写方法。
针对文本文件—— 字符流
字符流的输入流为Reader类,输出流为Writer类 。
针对二进制文件—— 字节流
字节流的输入流为InputStream类,输出流为OutputStream类 。
以上这四个类都是抽象类,都是用来对IO设备的读取,IO设备包括文件,网卡等等。
因此我们要对文件进行读取,就要实例这个抽象类的子类中专属文件读取的类, 在实例化时,需要为构造方法提供参数(String 路径或者File 对象) 。
- 实例化出来对象之后就相当于文件被打开, (产生了文件描述符), 使用完文件之后需要调用 close 方法关闭文件, 否则如果文件描述符表满了会产生文件资源泄露的严重bug
这四个抽象类都继承了Closeable接口,因此可以使用try语句,让他自动调用close方法。
try(InputStream inputStream = new FileInputStream("C:/music/test.txt")) {
//执行完try里的语句会自动调用close方法
}
1.针对文本文件—— 字符流
基本单位为:字符
字节流中输入流用到的是 Reader类 ,
输出流用到的是 Writer类
输入流 Reader类
输入流 Reader类
上图是要读文件中的内容。
一个字符一个字符的读
public static void main(String[] args) throws IOException {
try(Reader reader = new FileReader("C:/music/test.txt")) {
StringBuilder str = new StringBuilder();
while (true) {
// 无参数时,
// 会从第一个字符开始读
int a = reader.read();
if(a == -1) {
break;
}
char c = (char)a;
// 在字符串里拼接
str.append(c);
}
System.out.println(str.toString());
}
}
运行结果:
输出流 Writer类
输出流 Writer类
一个字符一个字符的写
public static void main(String[] args) {
try(Writer writer = new PrintWriter("C:/music/test.txt")) {
// 先清空内容
// 参数为一个字符时,写入字符
writer.append('盖');
writer.append('亚');
writer.append('来');
writer.append('啦');
} catch (IOException e) {
e.printStackTrace();
}
}
2.针对二进制文件—— 字节流
基本单位为:字节
字节流中输入流用到的是 InputStream类 ,
输出流用到的是 OutputStream类
输入流 InputStream类
输入流 InputStream类
上图是要读文件中的内容。
一个字节一个字节的读
public static void main(String[] args) throws IOException {
try(InputStream inputStream = new FileInputStream("C:/music/test.txt")) {
while (true) {
int a = inputStream.read();
// 无参数时,
// read方法会从第一个字节开始读,
// 并且返回每个字节的ASCII值,都读完了返回-1。
if(a == -1) {
break;
}
System.out.println(a);
}
}
}
utf-8字符集中一个汉字占三个字节,不同的字符集汉字所占字节不同
运行结果:
全部读完
public static void main(String[] args) throws IOException {
try(InputStream inputStream = new FileInputStream("C:/music/test.txt")) {
while (true) {
int a = inputStream.read();
if(a == -1) {
break;
}
System.out.println(a);
}
// available方法,返回文件内容一共有多少字节,返回类型是int
byte[] bytes = new byte[inputStream.available()];
// 参数为字节数组时,
// 将文件所有内容读入字节数组
int len = inputStream.read(bytes);
// 第一个参数表示被读的字节数组
// 第二个参数表示从几下标开始转换
// 表示要转换多少个字节
String str = new String(bytes,0,len);
System.out.println(str);
}
}
运行结果:
输出流 OutputStream类
输出流 OutputStream类
一个字节一个字节的写
public static void main(String[] args) throws IOException {
try(OutputStream outputStream = new FileOutputStream("C:/music/test.txt")) {
// 参数为int类型时,该参数表示ASCII值,
// 会先把文件中的内容清空,
// 再根据ASCII值往里一个字节一个字节的写入
outputStream.write(97);
outputStream.write(98);
outputStream.write(99);
}
}
全部写完
public static void main(String[] args) throws IOException {
try(OutputStream outputStream = new FileOutputStream("C:/music/test.txt")) {
String str = "炎龙侠好帅啊";
// 将字符串转换为字节数组
byte[] bytes = str.getBytes();
// 参数为字节数组时,
// 先清空文件内容,再将字节数组全部写入文件中
outputStream.write(bytes);
}
}
总结
以上就是今天要分享的内容了,本文介绍了两种针对文件的流,字节流与字符流,今天分享的内容比较简单啦啦啦🎉🎉🎉🎉。
路漫漫不止修身,也养性。