一.文件的相关概念
-
- 什么是文件?
文件是计算机中存储信息的基本单位。文件通常指的是存储在计算机或其他数字存储设备上的一段信息的集合,这些信息可以是文本、图片、音频、视频等不同格式的数据。
- 什么是文件?
-
- 文件路径: 文件的路径可以分为两类
- 相对路径:先指定一个"当前目录"/工作目录/基准目录,从该位置出发,找到目标文件.例如:./text.txt其中**.表示当前目录~如果有.**表示上层目录.
- 绝对路径:指的就是从树跟节点出发,一层一层最终到达目标文件.例如D:\IOTest\TestDemo1
-
- 文件的分类:
- 文本文件:此处的文本文件是按照文本/字符串来理解文本内容(即文件里面的二进制内容,都被表示为字符串).进一步理解可以认为二进制内容都是合法的字符串(文件存储的数据都是在指定的码表上可以查到~例如gbk/uft8/ascii).
- 二进制文件:二进制文件可能包含任何类型的数据,包括图像、音频、视频或其他非文本信息。
-
- 如何判断一个文件是文本文件还是二进制文件?
一个简单粗暴的办法就是用记事本打开,看到的内容是否是乱码,如果是乱码,则为二进制文件word / excel / power point<富文本> / exe / dll / 图片 / 音频 / 视频 / .class.如果不是乱码,是你能看懂的内容,则为文本文件(.c / .java / .cpp).
- 如何判断一个文件是文本文件还是二进制文件?
二.针对文件系统的操作.
包括不限于(创建文件 , 删除文件 , 重命名文件 , 列出目录内容… 就是右键能够进行的操作)
java.io.File类是文件和目录路径名称的抽象表示,主要用于文件和目录的创建、查找和删除等操作
File类详解.
构造方法:
-
public File(String pathname):通过将给定的路径名 字符串转换为抽象类路径 来创建新的实例
-
public File(String parent,String child):从父路径字符串 和 子路径字符串创建新的File实例
-
public File(File parent,String child):从父抽象路径名 和 子路径名字符串创建新的File实例
其他常用方法:
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
public class Test8 {
public static void main(String[] args) throws IOException {
//File file = new File("C:/IOTest/yt/test.txt");
File file = new File("./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.getCanonicalPath());
//其中.表示当前路径,此处是先一层一层找到IO这一级目录,然后再找.
//相当于原地踏步一下,此处的.就是IO这一级目录~~而后面哪一种就是绝对路径整理化简之后的结果.
System.out.println(file.exists()); //判断文件是否存在
System.out.println(file.isFile()); //判断是否是一个文件
System.out.println(file.isDirectory()); //判断是不是目录
boolean ret = file.createNewFile();
System.out.println("ret = "+ret);
//boolean ret = file.delete();
file.deleteOnExit(); //程序结束后删除文件
//程序结束之后再删除
//System.out.println(ret);
String[] files = file.list();
File[] files1 = file.listFiles(); //当前目录下的文件
System.out.println(Arrays.toString(files));
File file1 = new File("./aaa");
File file2 = new File("./aa/bb/cc");
//需要在构造方法中把路径创建好,再通过mkdir
boolean ret1 = file.mkdir();
boolean ret2 =file1.mkdirs();
System.out.println(ret1);
System.out.println(ret2);
File begin = new File("./test2.txt");
File dest = new File("./aaa/test.txt");
begin.renameTo(dest);
}
}
运行结果:
三.针对文件内容的操作.
IO流的核心概念是将不同的输入/输出源(如键盘、文件、网络连接等)抽象表述为“流”(stream)。这些流是从起源(source)到接收的(sink)的有序数据。在Java中,传统的流类型都放置在java io包下,用于实现各种输入和输出功能。
具体来说,IO流可以根据不同的分类方式分为多种类型:
- 按照流的流向:可以分为输入流和输出流。输入流用于从中读取数据,而不能向其写入数据;输出流则相反,只能向其写入数据,而不能从中读取数据。
- 按照处理数据单位的不同:分为字节流和字符流。字节流每次读取或写出一个字节,而字符流每次操作两个字节,适用于传输包含中文等字符的数据。
- 按照流的角色划分:节点流和处理流。节点流直接从或向一个特定的地方(节点)读写数据,而处理流则是对节点流的封装,提供了更高级的功能,如缓冲和格式化。
读写文件内容在各种编程语言中都是固定套路:①打开文件 ②关闭文件 ③读文件 ④.写文件
文件资源资源泄露:
关闭文件—>释放了文件的相关资源—>进程pcb中文件描述符表,记录了当前进程都打开了哪些文件—顺序表/数组 数组中每一个元素都是一个结构体这个结构体就是具体描述了你打开这个文件在文件系统上的一些属性.每次打开一个文件,都是需要在文件描述符表中占据一个位置的. 如果不关闭的话,还一直打开~~就会导致文件描述符表被耗尽.也叫做文件资源泄露
字节流:
Java IO包中以字节流进行读取文件的类是FileInputStream,它是InputStream(字节输入流)抽象类的子类。
代码示例:(有带缓冲区的和不带缓冲区的)
字节输入流
import java.io.*;
public class ioDemo7 {
public static void main(String[] args) throws IOException {
InputStream in = null;
try(InputStream in1 = new FileInputStream("./Test.txt")){
// //读文件
// //不知道文件有多少字节,使用while循环.
// while(true){
// int b = in1.read();
// if(b==-1){
// break;
// }
// //如果是中文,则打印的是utf8编码对应的值
// System.out.printf("%x ",b);
// }
while(true) {
byte[] buffer = new byte[1024];
//buffer是一个缓冲区,往往是一个内存空间
int n = in1.read(buffer);
if (n == -1) {
break;
}
for (int i = 0; i < n; i++) {
System.out.printf("%x ",buffer[i]);
}
}
}
}
}
字节输出流:
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
public class ioDemo9 {
public static void main(String[] args) throws IOException {
//append末尾添加
try (OutputStream out = new FileOutputStream("./Test.txt",true)){
byte[] buffer = new byte[]{97,98,99,100,101,102};
out.write(buffer);
}
}
}
字符流
字符输入流:
代码示例:
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
public class ioDemo10 {
public static void main(String[] args) throws IOException {
try (Reader in = new FileReader("./Test.txt")){
while(true) {
char[] buffer = new char[1024];
int n = in.read(buffer);
if(n==-1){
break;
}
String str = new String(buffer,0,n);
System.out.println(str);
for (int i = 0; i < n ; i++) {
System.out.print(buffer[i]);
System.out.print(" ");
}
}
}
}
}
字符输出流:
代码示例:
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
public class ioDemo11 {
public static void main(String[] args) throws IOException {
try (Writer writer = new FileWriter("./Test.txt",true)){
String str = "团子真帅";
writer.write(str);
}
}
}
注:
- read()无参数的版本.每次调用读取一个字节.返回值就表示读取到这个字节的值~~看起来是int实际上是byte实际取值是0-255,如果读取到文件末尾,继续读取,读取的值为-1.
- read(byte[] b) 一个参数版本,传入的字节数组参数,是一个输出型参数.byte[] 是引用类型.方法内部针对数组内容进行修改,方法执行结束后,方法外部也能生效.使用read的时候,往往就是定义一个内容为空的数组(不是努力了),把空数组交给read ,read内部对数组内容进行填充.
- read的第二三个版本返回的int表示实际读取的自己个数,默认情况下,read会尝试把数组填满但是文件的实际剩余长度可能不足以填满, 此时返回值就是告诉你实际填充了多少个字节
- OutputStream 默认的情况下,会把之前文件的内容清空掉(不是write引起的,而是打开操作引起的),然后从头重新写.
- 使用字符流读取汉字的时候,一个char占两个字节,一个汉字(utf8编码)占三个字节,此时按字符打印汉字就会出现问题,汉字打印不出来. 相当于在读取的时候,把文件中的utf8在按照字符读取的时候,先转成Unicode,每个char中存的是Unicode的值~~如果基于Unicode最终还可以构造回utf8的String
- Scanner 也可以使用Scanner来辅助咱们读取文件~~Scanner(System.in) 本质上是一个inputStream