本篇会加入个人的所谓鱼式疯言
❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言
而是理解过并总结出来通俗易懂的大白话,
小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的.
🤭🤭🤭可能说的不是那么严谨.但小编初心是能让更多人能接受我们这个概念 !!!
引言
在数字化时代,数据的存储、访问与处理已成为推动科技进步与社会发展的核心动力。
想象一下,从个人电脑的文档管理到企业级的数据中心,从智能手机上的照片备份到云端服务的海量数据存储,无一不依赖于一个关键而基础的技术—— 文件输入输出(File IO) 。
文件IO,作为连接数据世界与现实世界的桥梁,其重要性不言而喻。它不仅关乎数据的安全与效率,更是各类应用程序、操作系统乃至整个信息技术架构的基石。
让我们一同踏入这场探索之旅,揭开文件IO技术的神秘面纱,共同见证数据如何在指尖流转,成为推动世界前行的强大力量。
本篇文章中我们讲学习到以下内容
目录
-
文件系统操作
-
文件内容操作
-
文件综合运用操作
一. 文件系统操作
对于一个文件来说,我们可以得到一个文件的各种属性: 文件名,文件目录,文件路径。这里的就涉及到文件系统操作。
1. File类
在 Java标准库 中就封装了一个
FIle类
来获取文件的各种信息和属性
来自
java.io.File
这个包。
2. 常用方法
而作为一个后端开发的程序猿我们只需要了解 Java标准库
中的 File 类 中常用的几个方法即可:
- 得到该 对象的文件名和上一个路径的文件
- 得到该 对象的路径
- 判断该对象是否是 绝对路径 或者 是否是一个目录
- 判断该对象是否是
一个文件
- 得到该目录下的 所有文件和目录
3. 代码演示
package FileDemo;
import java.io.File;
import java.io.IOException;
public class MyFileTest {
public static void main(String[] args) throws IOException {
File file = new File("./demo.txt");
// 得到文件的绝对路径
System.out.println(file.getAbsoluteFile());
// 判断是否是目录
if (file.isDirectory()) {
System.out.println("是目录!");
} else {
System.out.println("不是目录!");
}
// 判断是否是路径
if (file.isAbsolute()) {
System.out.println("是路径!");
} else {
System.out.println("不是路径!");
}
// 得到上一级的文件
File[] files = file.getParentFile().listFiles();
// 开始遍历
for (File f : files) {
// 判断是否是文件
if (f.isFile()) {
System.out.println(f.getName());
}
}
}
}
在上面的演示中
主要分为两部进行
- 文件对象的实例
File file = new File("./demo.txt");
- 进行各种文件系统操作
// 得到文件的绝对路径
System.out.println(file.getAbsoluteFile());
等… 这些操作将在下面内容中结合 文件内容操作 一起配合使用~
鱼式疯言
- 使用 File 类来实例化对象 时, 也是会成功的,
但需要判断的是是否是 符合要求 的
目录
或路径
。
- 需要抛出
异常 IOException
这个异常, 并且导入 Java.io.IOException 这个包.
二. 文件内容操作
在文件内容操作的之前,小伙伴们必须先了解一下流对象,以及流对象的表示形式。
1. 流对象
什么是流 ? ? ?
流可以说水流,气流等…
但在文件IO这里,流的作用主要是处理各种各样的文件形式而形成的一种 统一的概念 。
而流分为两种:
1) 字节流
2) 字符流
<1>. 字节流
字节流的含义就好比现在你有一百个字节数据
如果一个字节一个字节取,就需要取一百次;
如果五个字节五个字节取,就需要取二十次;
如果十个字节十个字节取,就需要取十次;
如果二十个字节二十个字节取,就需要取五次;
如果一百个字节一百个字节取,只需取一次。
这就是字节流,先把数据 以字节为基本单位
进行划分,根据 需求
得到每次 需要取出字节的个数 来进行 文件IO内容操作
。
代表的类:
- 以字节为单位的读操作的类
InputStream
- 以字节为单位的写操作的类
OutputStream
<2>. 字符流
字符流的含义就好比现在你有一百个字符数据
如果一个字符一个字节取,就需要取一百次;
如果五个字符五个字节取,就需要取二十次;
如果十个字符十个字节取,就需要取十次;
如果二十个字符二十个字节取,就需要取五次;
如果一百个字符一百个字节取,只需取一次。
字符流是以字符为 基本单位对文件内容进行划分并操作。
代表的类:
-
以字符为单位的读操作的类:
Reader
-
以字符为单位的写操作的类:
Writer
2. 字符流代码演示
<1>. 读操作
package MyIODemo;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class ReaderDemo {
public static void main(String[] args) throws IOException {
// 实例化字符流读操作的FileReader类
// 打开文件
Reader reader = new FileReader("demo1.txt");
// 利用文件流对文件进行读操作
// 通过循环遍历每次读的字符
while(true) {
// 将每次读到的字符 用 n 来接收
int n = reader.read();
// 一旦返回 -1 说明读取到文件的最后一个位置,读取完毕
if(n== -1) {
break;
}
// 转化为字符并打印输出
char buffer = (char) n;
System.out.print(buffer);
}
// 关闭文件流
reader.close();
}
}
读操作 用到的 Reader类 来自
java.io.Reader
这个包, 而且需要抛出IOException
这个类.
鱼式疯言
总结一 :
文件内容操作的流程三部曲:
- 打开文件
- 读写文件内容
- 关闭文件
总结二 :
FileNotFoundException
是进行打开文件是 所需要抛出的异常 , 但属于IOException
, 所以这里我们只需要抛出IOException
即可。
<2>. 写操作
package MyIODemo;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.Scanner;
public class WriterDemo {
public static void main(String[] args) throws IOException {
// 打开文件
Writer writer = new FileWriter("demo1.txt",true);
Scanner in = new Scanner(System.in);
String buffer = in.nextLine();
// 写文件
writer.write(buffer);
// 关闭文件
writer.close();
}
}
结论一 :
对于 写操作 , 还是按照三个流程:
- 打开文件
- 写文件
- 关闭文件
结论二:
// 打开文件
Writer writer = new FileWriter("demo1.txt",true);
当我们打开文件时:
FileWriter
方法还设定了 一个参数 , 这个参数的如果置为true
就代表不会清空全有数据而是在原有数据的后面进行拼接写入。
如果在参数列表 ==不添加
true
或者置为false
==, 就会清空内容
,从一个 空文档 开始写入。
鱼式疯言
关于 文件关闭
这件事,小编有话说
在操作系统内核中,每打开一个文件,就会在操作系统中的一个特点的区域: “文件描述符表” 中多一个 项 。
这个 文件描述符表 可以看成是
一个数组
, 一旦打开文件过多没有及时关闭 ,就会在 文件描述符表中 不断堆积 , 就会导致出现文件泄露问题
虽然进程结束,程序会 自动清空文件描述符表中的每一项 , 但是如果程序一直
不结束
,就会导致 不可预估的问题 发现。
所以小编在这里建议: 加上
close()
方法来 释放文件资源 。
3. 字节流代码演示
<1>. 读操作
package MyIODemo;
import java.io.*;
import java.util.Scanner;
/**
* 基本版本的读入文件
*/
public class StreamTest {
public static void main(String[] args) {
try(InputStream inputStream = new FileInputStream("./demo.txt")){
while(true) {
byte[] buffer = new byte[1024];
int flg = inputStream.read(buffer);
if(flg == -1) {
break;
}
for (int i = 0; i < flg; i++) {
System.out.print((char) buffer[i]);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这里字节流的读操作
- 在 打开文件 时
小编利用了
try() catch {}
进行操作。
利用 try (打开文件) , 在这个括号打开文件 在{} 内生效,出来{} 就会自动关闭
文件流
。 这样就可以省去手动close()关闭文件
。
byte[] buffer = new byte[1024];
int flg = inputStream.read(buffer);
- 在读文件时,我们就需要注意声明一个
byte[] 类型
的数组, 用来 存储文件中的数据, 只需要放入read
的参数中 即可填充 , 而flg
的这个返回值就是作为 数组实际填充 的大小, 如果一旦flg = -1
时, 就说明数据已经返回结束了。
其他操作和上面字符流大体一致,小编在这就不赘述啦 💖 💖
鱼式疯言
注意事项:
只有这种特定的 打开文件类似的操作 才能放入
try ()
的括号内, 且如果要放 多行 的话,就需要用;
号来隔开。 作用域就是在{ }
。
<2>. 写操作
package MyIODemo;
import java.io.*;
import java.util.Scanner;
/**
* 基本版本的写入文件
*/
class StreamTest2 {
public static void main(String[] args) {
try(OutputStream outputStream = new FileOutputStream("./demo.txt",true)) {
byte[] buffer = {97,98,99};
outputStream.write(buffer);
}catch (IOException e){
e.printStackTrace();
}
}
}
字节流的写操作也大同小异,小编在这里就不赘述, 小伙伴好好理解即可。
三. 文件综合运用操作
学会了文件系统和文件内容的各个基础操作,下面小编就举出两个实际的案例给小伙伴演示下两者结合的秒出哦 , 可千万别眨眼哦 💖 💖 💖 💖
1. 找到指定文件确认是否删除
<1>. 逻辑分析
- 首先: 先确认该文件的路径
- 其次: 在 路径合法 的情况下, 把每个文件目录取出进行递归查找
- 最后:在是合法文件的提前下, 判断是否含有 该文件名 ,一旦含有就选择 是否需要删除
<2>. 代码展示
/**
* 查找指定文件并且删除
*
*/
package MyIODemo;
import java.io.*;
import java.util.Scanner;
class StreamTest4 {
public static void main(String[] args) {
// 确定路径
System.out.print("请输入指定路径: ");
Scanner in = new Scanner(System.in);
String path = in.next();
// 转化成路径
File pathRoot = new File(path);
// 判断是否是合法路径
if(!pathRoot.isDirectory()) {
System.out.println("不是合法路径!");
return;
}
// 输入指定文件
System.out.print("请输入指定的文件的关键字: ");
String key = in.next();
// 进行递归
scan(pathRoot, key);
}
private static void scan(File pathRoot, String key) {
// 判断当前路径是否合法
if(!pathRoot.isDirectory()) {
return;
}
// 合法的情况下取出当前所以的路径
File[] files = pathRoot.getAbsoluteFile().listFiles();
// 多加一层判断
if (files== null || files.length == 0) {
return;
}
// 深度优先遍历 所以的文件路径
for(File file : files) {
if(file.isFile()) {
// 是文件的话就开始判断是不是指定文件
// 然后进行删除
delete(file, key);
} else {
// 继续往下递归
scan(file,key);
}
}
}
private static void delete(File file, String key) {
if(file.getName().contains(key)) {
System.out.println("请确定是否删除该文件:" + file.getAbsoluteFile() + " Y/y -> 是, N/n -> 否 : ");
Scanner in = new Scanner(System.in);
String str = in.next();
if(str.equals("y") || str.equals("Y")) {
file.delete();
System.out.println("删除成功!");
} else {
System.out.println("删除失败,正在退出...");
}
}
}
}
2. 进行文件的复制
<1>. 逻辑分析
- 首先输入第一个字符串为 源文件, 判断是否是 合法文件 。
- 其次输入第二个字符串为 目标文件, 判断是否是 合法文件。
- 最后在 try catch 中实例化 字节输出和输入流 ,先对源文件进行
读操作
, 然后再对目标文件进行写操作
。当源文件 读取结束 ,目标文件也就完成了拷贝
。
<2>. 代码展示
/**
*
* 将一个文件拷贝到另外一个文件
*
*/
import java.io.*;
import java.util.Scanner;
class StreamTest5 {
public static void main(String[] args) {
System.out.print("请输入源文件路径: ");
Scanner in = new Scanner(System.in);
String path = in.next();
File curPath = new File(path);
// 判断是否合法路径
// 是否是正确的文件
if(!curPath.isFile()) {
System.out.println("源文件非法!");
return;
}
// 判断是否合法
System.out.print("请输入目标文件的路径: ");
path = in.next();
File descPath = new File(path);
if (!curPath.getParentFile().isDirectory()) {
System.out.println("目标文件路径非法");
return;
}
// 开始进行读入 和写出
try (InputStream inputStream = new FileInputStream(curPath) ;
OutputStream outputStream = new FileOutputStream(descPath)) {
byte[] buffer = new byte[1024];
// 从源文件读入, 写出到目标文件
while(true) {
// 读入
int n = inputStream.read(buffer);
if(n==-1) {
break;
}
// 写出
outputStream.write(buffer,0,n);
}
System.out.println("拷贝成功! ");
} catch (IOException e) {
e.printStackTrace();
}
}
}
总结
-
. 文件系统操作: 利用
File
这个类对文件的 路径,目录,判断 进行各种操作。 -
. 文件内容操作: 熟悉了
文件流
的 字节流和 字符流 的 概念理解 , 以及对于FileReader
,IntputStream
的读操作, 和FileWriter
和OutputStream
的 写操作。 -
. 文件综合运用操作: 综合 结合了两种不同的 文件系统操作和文件内容操作 结合学习,实际运用了具体的实际运用中。
如果觉得小编写的还不错的咱可支持 三连 下 (定有回访哦) , 不妥当的咱请评论区 指正
希望我的文章能给各位宝子们带来哪怕一点点的收获就是 小编创作 的最大 动力 💖 💖 💖