🎇🎉🎉🎉点进来你就是我的人了
博主主页:🙈🙈🙈戳一戳,欢迎大佬指点!
人生格言: 当你的才华撑不起你的野心的时候,你就应该静下心来学习!
欢迎志同道合的朋友一起加油喔 💪💪💪
目标梦想:进大厂,立志成为一个牛掰的Java程序猿,虽然现在还是一个🐒嘿嘿
谢谢你这么帅气美丽还给我点赞!比个心
1.File类
-
java.io.File类是文件和目录路径名称的抽象表示,主要用于以下几个操作:
-
列出目录中有哪些文件
-
创建文件
-
创建目录
-
删除文件
-
重命名文件
-
…等等
-
Java标准库提供了 File 类表示一个文件,进一步的通过 File 提供的方法,就可以进行文件系统操作了。
(针对文件系统进行操作)File类概述、构造方法、方法以及几个案例
1.1File类对文件进行操作
package test;
import java.io.File;
import java.io.IOException;
public class Test01 {
public static void main(String[] args) throws IOException {
//将文件封装成一个 File 类对象
//在windows,dos 中,系统默认用 “\”作为路径分隔符
//在Unix/Linux 中,使用“/”作为路径分隔符
File f = new File("d:\\test.txt");
File f1 = new File("d:\\test.txt");
File f2 = new File("d:/test.txt");
// File.separator 属性帮我们获取当前操作系统的路径拼接符号
// String separator = File.separator;
// File.separator 是一个常量,用于表示文件路径分隔符,
// 它会根据当前操作系统自动选择合适的分隔符(在Windows系统中为 \,在Unix/Linux系统中为 /)。
File f3 = new File("d:" + File.separator + "test.txt");
System.out.println("文件是否可读:" + f.canRead());
System.out.println("文件是否可写:" + f.canWrite());
System.out.println("文件的名字:" + f.getName());
System.out.println("文件的上级目录路径:" + f.getParent());
System.out.println("是否是一个文件:" + f.isFile());
System.out.println("是否是一个目录:" + f.isDirectory());
System.out.println("文件是否隐藏:" + f.isHidden());
System.out.println("文件的大小:" + f.length());
System.out.println("文件是否存在:" + f.exists());
// //对文件存在进行一个判断
// if (f.exists()){//文件存在
// //删除文件
// f.delete();
// }else {
// //文件不存在,创建文件
// f.createNewFile();//这里应该抛出一个 IO 异常
// }
// System.out.println(f == f1);//比较两个文件的地址(这种比较方法是错误的)
//它比较的是对象的引用是否相同,即它们是否指向内存中的同一个对象。
System.out.println("判断两个文件的地址是否一样:" + f.equals(f1));
//接下来是与文件路径相关的
System.out.println("绝对路径:" + f.getAbsolutePath());
System.out.println("父目录文件路径:" + f.getParent());
System.out.println("toString:" + f.toString());
System.out.println("----------------------------------");
File f4 = new File("./demo.txt");
if (!f4.exists()){
f4.createNewFile();
}
System.out.println("父目录文件路径:" + f4.getParent());
//绝对路径:D:\2024\class-room-code\J20240714\demo.txt
System.out.println("绝对路径:" + f4.getAbsolutePath());
System.out.println("修饰过的绝对路径:" + f4.getCanonicalPath());
}
}
1.2File类对目录进行操作
package test;
import java.io.File;
public class Test02 {
public static void main(String[] args) {
//将目录封装为File类的对象:
File f = new File("D:/IDEA");
System.out.println("文件是否可读:"+f.canRead());
System.out.println("文件是否可写:"+f.canWrite());
System.out.println("文件的名字:"+f.getName());
System.out.println("上级目录:"+f.getParent());
System.out.println("是否是一个目录:"+f.isDirectory());
System.out.println("是否是一个文件:"+f.isFile());
System.out.println("是否隐藏:"+f.isHidden());
System.out.println("文件的大小:"+f.length());
System.out.println("是否存在:"+f.exists());
System.out.println("绝对路径:"+f.getAbsolutePath());
System.out.println("相对路径:"+f.getPath());
System.out.println("toString:"+f.toString());
System.out.println("---------------------");
//跟目录相关的方法:
File f2 = new File("D:/b/b/c/c");
File f3 = new File("D:\\c\\b\\c");
//创建目录:
// f2.mkdir();//创建单层目录
f2.mkdirs();//创建多层目录
//删除:如果是删除目录的话,只会删除一层,并且前提:这层目录是空的,里面没有内容,如果内容就不会被删除
f2.delete();
//查看:
String[] list = f.list();//文件夹下目录/文件对应的名字的数组
for(String s:list){
System.out.println(s); //只能输出文件名
}
System.out.println("=========================");
File[] files = f.listFiles();//作用更加广泛
for(File file:files) {
//能通过对象去获取名字和路径等等
System.out.println(file.getName() + "," + file.getAbsolutePath());
}
}
}
2.常用IO流
- 所有流都实现了 Closeable 接口,都有close()方法,流用完要关闭。
- 所有的输出流都实现了Flushable接口,都有flush()方法,flush()方法的作用是:将缓存清空,全部写出。养成好习惯,以防数据丢失。
- 和File相关的IO流有四个分别是:
- FileInputStream
- FileOutputStream
- FileReader
- FileWriter
- 其中FileReader和 FileWriter为字符IO流
- FileInputStream和FileOutputStream为字节IO流
3.读文件
3.1字节流–InputStream、FileInputStream 概述
- InputStream 只是⼀个抽象类 ,要使⽤还需要具体的实现类。关于 InputStream 的实现类有很多 ,基本可以认为不同的输⼊设备都可以对应⼀个 InputStream 类 ,我们现在只关⼼从⽂件中读取 ,所以使⽤ FileInputStream
- 文件字节输入流,可以读取任何文件
InputStream方法:
修饰符及返回值类型 | ⽅法签名 | 说明 |
---|---|---|
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() | 关闭字节流 |
FileInputStream 构造方法:
- 针对硬盘文件进行操作
签名 | 说明 |
---|---|
FileInputStream(File file) | 利⽤ File 构造⽂件输⼊流 |
FileInputStream(String name) | 利⽤⽂件路径构造⽂件输⼊流 |
📚打开文件
- 如果打开成功,没有出现异常之类,接下来就可以读取文件内容了
InputStream inputStream = new FileInputStream("d:/test.txt")
- 对于这一行代码,打开文件成功后,就得到了 InputStream 对象,后续针对文件的操作,就都是通过这个对象展开的。
- 再者,我们操作硬盘不方便直接操作,在内存里构造一个和它关联的对象,操作这个对象就相当于操作硬盘数据。
- 上述操作对象相当于操作硬盘数据,就类似于遥控器,我们开空调的时候,不可能每次借助梯子爬上去,用手摁下空调开关,而是通过空调遥控器去操作空调。
📚关闭文件
inputStream.close();//非常关键的操作
为什么要关闭文件???
- 关闭文件主要是为了释放文件描述符表资源。
文件描述符表,这个表就相当于是个数组,这个数组的下标就称为 “文件描述符”,每次打开一个文件,都会在文件描述符表中占据一个位置;每次关闭文件,都会释放一个位置。并且文件描述符表,是存在上线的,如果一个进程,一直在打开文件,没有释放,此时就会导致我们的进程在进行后续打开文件操作的时候,就会打开文件失败!!
📚读取文件
📄Read()实例
public static void main(String[] args) throws IOException {
//打开文件
InputStream inputStream = new FileInputStream("d:/test.txt");
while (true){
//一个字节一个字节进行读取
int i = inputStream.read();
if (i == -1){
//读取完毕
break;
}
System.out.printf("0x%x ", i);
}
//关闭文件
inputStream.close();
}
📄Read(byte[ ] b)实例
public static void main(String[] args) throws IOException {
InputStream inputStream = new FileInputStream("d:/test.txt");
while (true){
byte[] bytes = new byte[1024];
int n = inputStream.read(bytes);
if (n == -1) {
//读取完毕。n 就是 -1
break;
}
for (int i = 0; i < n; i++) {
System.out.printf("ox%x ",bytes[i]);
}
}
inputStream.close();
}
注意: 如果是读取中文,UTF8 的编码格式,一个汉字占3个字节。
如果要想读取中文在控制台,字节流只能通过指定编码格式,就比较麻烦。例如以下代码:
public static void main(String[] args) throws IOException {
// 1.打开文件
InputStream inputStream = new FileInputStream("d:/test.txt");
// 2.读取文件
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
String s = new String(buf, 0, len, "UTF8");
System.out.println(s);
// 3.关闭文件
inputStream.close();
}
3.2字符流–Reader、FileReader
- 和字节流方法差不多
📄Read(byte[ ] b)实例
public static void main(String[] args) throws IOException {
// 字符流
Reader reader = new FileReader("d:/test.txt");
char[] buffer = new char[1024];
int len = reader.read(buffer);
for(int i = 0; i < len; i++) {
System.out.println(buffer[i]);
}
reader.close();
}
3.3利⽤ Scanner 进⾏字符读取
- 上述例⼦中 ,我们看到了对字符类型直接使⽤ InputStream 进⾏读取是⾮常⿇烦且困难的,所以,我们使⽤⼀种我们之前⽐较熟悉的类来完成该⼯作 ,就是 Scanner 类。
构造⽅法 | 说明 |
---|---|
Scanner(InputStream is, String charset) | 使⽤ charset 字符集进⾏ is 的扫描读取 |
public static void main(String[] args) throws FileNotFoundException {
InputStream inputStream = new FileInputStream("d:/test.txt");
Scanner scanner = new Scanner(inputStream,"utf-8");
while (scanner.hasNext()){
String s = scanner.next();
System.out.println(s);
}
}
3.4对关闭资源 close() 进行优化
- 我们在前面字节流读取中文的代码中,发现如果在 read() 读文件的过程中出现异常,就可能导致 close() 执行不到,按照我们以前的思路,使用 try…catch…finally,将关闭资源放在 finally 中。
public static void main(String[] args) {
InputStream inputStream = null;
try {
// 打开文件(字节流)
inputStream = new FileInputStream("d:/test.txt");
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
// 读取中文
String s = new String(buf, 0, len, "UTF8");
System.out.println(s);
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 更推荐的做法是以下做法:
public static void main(String[] args) {
try (InputStream inputStream = new FileInputStream("d:/test.txt")) {
byte[] buf = new byte[1024];
int len = inputStream.read(buf);
// .........
} catch (IOException e) {
e.printStackTrace();
}
}
注意:创建对象写在 try 后面的 括号里面
4.写文件
4.1字节流 – OutputStream、 FileOutputStream概述
OutputStream方法:
修饰符及返回值类型 | ⽅法签名 | 说明 |
---|---|---|
void | write(intb) | 写⼊要给字节的数据 |
void | write(byte[] b) | 将 b 这个字符数组中的数据全部写 ⼊ os 中 |
int | write(byte[] b, intoff, int len) | 将 b 这个字符数组中从 off 开始的 数据写⼊ os 中 ,⼀共写 len 个 |
void | close() | 关闭字节流 |
void | flush() | 重要:我们知道 I/O 的速度是很慢 的 ,所以 ,⼤多的 OutputStream 为了减少设备操作的次数 ,在写数 据的时候都会将数据先暂时写⼊内 存的⼀个指定区域⾥ ,直到该区域 满了或者其他指定条件时才真正将 数据写⼊设备中 ,这个区域⼀般称 为缓冲区。但造成⼀个结果 ,就是 我们写的数据 ,很可能会遗留⼀部 分在缓冲区中。需要在最后或者合 适的位置 ,调⽤ flush(刷新)操 作 ,将数据刷到设备中。 |
- OutputStream 同样只是⼀个抽象类 ,要使⽤还需要具体的实现类。我们现在还是只关⼼写⼊⽂件 中 ,所以使⽤ FileOutputStream
📚利⽤ OutputStream Writer 进⾏字符写⼊
public static void main(String[] args) throws IOException {
try (OutputStream outputStream = new FileOutputStream("d:/test.txt")){
outputStream.write('H');
outputStream.write('e');
outputStream.write('l');
outputStream.write('l');
outputStream.write('o');
outputStream.flush();
}
}
public static void main(String[] args) throws IOException {
try (OutputStream outputStream = new FileOutputStream("d:/test.txt")){
byte[] bytes = new byte[]{
(byte) 'G',(byte) 'o',(byte) 'o',(byte) 'd'
};
outputStream.write(bytes);
outputStream.flush();
}
}
- 注意:以上两个代码案例
每次重新写的时候,都会把旧的文件内容清空掉,重新去写。
但是这种原生字节流的写文件方法,用起来还是不方便。
4.2字符流 – Writer、FileWriter
- 代码示例
public static void main(String[] args) {
try (Writer writer = new FileWriter("d:/test.txt")) {
// 能写字符串,就很方便
writer.write("hello world");
} catch (IOException e) {
e.printStackTrace();
}
}
- 我们的这个字符流中的 Writer 还能写字符串,就很方便。还有一种方式 – PrintWriter ,它提供了更丰富的写。
📚利⽤ PrintWriter 找到我们熟悉的⽅法
- 上述 ,我们其实已经完成输出⼯作 ,但总是有所不⽅便 ,我们接来下将 OutputStream 处理下 ,使⽤ PrintWriter 类来完成输出 ,因为PrintWriter 类中提供了我们熟悉的 print/println/printf ⽅法
public static <outputStreamWriter> void main(String[] args) throws IOException {
try (OutputStream outputStream = new FileOutputStream("d:/test.txt");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream,"utf-8");
PrintWriter printWriter = new PrintWriter(outputStreamWriter)) {
printWriter.println("我是第一行");
printWriter.print("我的第⼆⾏\r\n");
printWriter.printf("%d: 我的第三⾏\r\n", 1 + 1);
printWriter.flush();
}
}
5.try-with-resources
-
try-with-resources是Java 7中引入的一个特性,它是为了简化在程序中使用资源(例如文件、网络连接等)的管理。在Java程序中,资源的正确关闭非常重要,因为资源泄漏可能导致性能问题、程序错误或其他问题。try-with-resources语句确保在代码块执行完毕后自动关闭资源,无论代码执行过程中是否发生异常。
-
try-with-resources语句实现自动关闭资源的方式是通过在资源实现java.lang.AutoCloseable或java.io.Closeable接口的情况下,确保close()方法被调用。这两个接口都包含一个close()方法,它们的实现负责释放资源。
5.1try-with-resources 代码案例
public static void main(String[] args) throws IOException {
try (InputStream inputStream = new FileInputStream("d:/test.txt")){
while (true){
byte[] bytes = new byte[1024];
int n = inputStream.read(bytes);
if (n == -1) {
//读取完毕。n 就是 -1
break;
}
for (int i = 0; i < n; i++) {
System.out.printf("ox%x ",bytes[i]);
}
}
}
}
注意:创建对象写在 try 后面的 括号里面
当程序执行到try语句块结束时,如果resource实现了AutoCloseable或Closeable接口,那么close()方法将被自动调用。这确保了无论try块中是否抛出异常,资源都会被正确关闭。
因此,try-with-resources语句可以自动关闭资源,主要是因为它依赖实现AutoCloseable或Closeable接口的资源,使得在try语句块结束时自动调用close()方法。这简化了资源管理,降低了资源泄漏和相关问题的风险。
注意:如果一个资源没有实现AutoCloseable或Closeable接口,那么try-with-resources语句将无法自动关闭该资源。在这种情况下,你需要在代码中手动管理资源的关闭。