前言
我们无时无刻不在操作文件。可以说,我们在电脑上能看到的图片、视频、音频、文档都是一个又一个的文件,我们需要从文件中读取我们需要的数据,将数据运算后也需要将结果写入文件中长期保存。可见文件的重要性,今天我们就来简单介绍一下Java中关于文件的操作和读写。
什么是文件
我们日常生活中也有关于文件的概念,它们一般是这样的:
计算机中文件的概念完全可以从日常生活中的文件类比出来。我们知道计算机可以存储多种多样的数据类型,可以是图片,可以是音频……但不同形式的数据如何更加高效的管理呢,我们就抽象出文件的概念,上面提及到的类型都可以从属于文件这个大的体系下,我们不在关注我们操作的具体是什么,因为我们操作的都是文件。这大大降低了学习和使用的成本。当然文件存储的除了数据以外也存储了维护文件的信息,被称为文件源信息。
随着文件的越积越多,文件的管理和组织方式成为一个让人头疼的东西。最终我们从日常的文件管理中获得灵感,选取文件夹/目录的形式管理文件,其中的数据结构使用的是多叉树的树形结构
路径(Path)
如何定位到唯一的文件,这就是路径的概念。路径可以分为绝对路径和相对路径。
绝对路径指的是从系统根目录出发到达目标文件的完整路径,它是唯一的
相对路径指的是从源位置到目标文件的路径,选取不同的源位置路径也是不同的
就好比学校的位置,如果是绝地路径指的是它的经纬度,相对路径指的是从家到学校的路径,所有人的家在不一样的位置这个相对路径也不同,但这个经纬度对于任何位置都是唯一的
文件的分类
文件可以分为二进制文件和文本文件。常见的二进制文件有图片,视频……文本文件有txt文件。两者的本质区别就在于,文本文件中存储的字符,二进制文件存储的是01。但文本文件在硬盘上本质上存储的依然是二进制01,只不过在逻辑上文本文件会将字符转换成对应的二进制进行存储。
快速区分这两者的办法就是用记事本打开,看得懂的是文本文件,看不懂的是二进制文件。
其他
Windows系统用文件的后缀标识文件的类型和默认的打开方式。Windows系统可以为文件设置权限。Windows还有一类特殊的文件,就是快捷方式,本质上就是文件引用。为了操作方便,很多操作系统将所有I/O设备都抽象成文件
文件操作(File类)
文件操作我们只需要介绍一个类——File
Java 中通过 java.io.File 类来对一个文件(包括目录)进行抽象的描述。注意,有 File 对象,并不
代表真实存在该文件,File不涉及文件的读写
属性
pathSeparatorChar(char)和 pathSeparator(String) 代表文件的路径分隔符,自动获取
构造方法
其中,如果需要使用相对路径,一般用 . 表示本目录 用 .. 表示上级目录。
方法
package www.Zheng;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
/**
* @Title: Demo1
* @Author zyh
* @Package www.Zheng
* @Date 2024/7/7 16:41
* @description: 文件操作方法
*/
public class Demo1 {
public static void main7(String[] args) {
File file = new File("./test.txt");
System.out.println(file.canRead());//boolean canRead()判断是否有读取权限
System.out.println(file.canWrite());//boolean canWrite()判断是否有写入权限
}
public static void main(String[] args) {
File file = new File("./test.txt");
File file2 = new File("./test/ttt.txt");
System.out.println(file.renameTo(file2));// boolean renameTo文件改名,逻辑是将源文件剪切,在目标位置粘贴在重命名
}
public static void main5(String[] args) {
File f = new File("./test");
System.out.println(f.mkdir());// boolean mkdir() 创建一级目录
File file = new File("./test/test1");
System.out.println(file.mkdirs());//boolean mkdirs() 创建多级目录
}
public static void main4(String[] args) throws IOException {
File parent = new File("./");
for (String s: parent.list()) {// String[] list()得到本目录下所有的文件名
System.out.println(s);
}
System.out.println(Arrays.toString(parent.list()));
for (File file : parent.listFiles()) {//File[] listFiles()得到本目录下所有的文件
System.out.println(file.getCanonicalPath());
}
}
public static void main3(String[] args) throws InterruptedException {
File parent = new File("./");
File file = new File(parent,"/test.txt");
file.delete();// boolean delete()将文件立即删除
file.deleteOnExit();// void deleteOnExit()将文件标记未删除,JVM运行结束后删除
Thread.sleep(2000);
System.out.println("程序结束");
}
public static void main2(String[] args) throws IOException {
File parent = new File("./");
File file = new File(parent,"/test.txt");
System.out.println(file.exists());
System.out.println(file.isDirectory());//boolean isDirectory() 判断文件是否未文件夹/目录
System.out.println(file.isFile());// boolean isFile()判断文件是否未普通文件
file.createNewFile();//boolean createNewFile()新建file指定路径的文件
System.out.println(file.exists());
System.out.println(file.isDirectory());
System.out.println(file.isFile());
}
public static void main1(String[] args) throws IOException {
File parent = new File("./");
File file = new File(parent,"/test.txt");
System.out.println(file.exists());// boolean exists() 判断File文件是否真是存在
System.out.println(file.getParent()); //String getParent() 返回 File 对象的父目录文件路径
System.out.println(file.getName()); //String getName()返回 File 对象的文件名称
System.out.println(file.getPath()); // String getPath() 获得文件的路径,如果初始化使用的是相对路径得到的是相对路径,如果初始化使用的是绝对路径得到的是绝对路径
System.out.println(file.getAbsolutePath());//String getAbsolutePath() 获得绝对路径,未修饰
System.out.println(file.getCanonicalPath());// String getCanonicalPath()获得绝对路径,修饰
//修饰和未修饰在初始化传入绝对路径时没有区别,在传入相对路径时修饰会将 ./ 删除
}
}
什么是流
流是什么?流其实就是对IO设备的封装。我们可能会向不同的IO设备上读写数据,这显然是件很麻烦的事情,意味着我们需要为不同的IO设备都设计一种代码。这时候我们就引入了流的概念,将所有的IO设备都封装在流里面,这时候我们只需要向流内读写数据即可
文件的读写操作(流操作)
我们根据操作文件的类型可以分为字节流和字符流,再根据读写可分为字节输入流,字节输出流,字符输入流,字符输出流。主要对应的是四个抽象类,分别是
InputStream//字节输入流
OutputStream//字节输出流
Reader//字符输入流
Writer//字符输出流
上面四个都是抽象类,使用我们需要使用它们的实现类。这里我们只关心文件,用的都是File相关的实现类,理论上不同的IO设备都会有具体的实现类。
InputStream inputStream = new FileInputStream();
OutputStream outputStream = new FileOutputStream();
Reader reader = new FileReader();
Writer writer = new FileWriter();
上面四个实现类均需要传入File或者文件路径以定位到操作文件
下面我们来简单的认识一下这四个实现类
FileInputStream
读取
public int read() throws IOException 读取一个字节,返回值-1则代表读完否则代表读到的内容
public int read(byte b[]) throws IOException 将读取的内容尽量填满数组,返回值代表读到的有效数,-1则代表读完
public int read(byte b[], int off, int len) throws IOException 将读取的内容尽量填满数组从off后len个元素,返回值代表读到的有效数,-1则代表读完
关闭
public void close() throws IOException 资源回收
FileOutputStream()
写入
public void write(int b) throws IOException 写入一个字节的数据
public void write(byte b[]) throws IOException 将数组内的数据写入
public void write(byte b[], int off, int len) throws IOException 将数组从off往后len个元素的数据写入
public void close() throws IOException 资源回收
public void flush() throws IOException 刷新缓存区。因为IO操作的速度很慢,为了提高效率,一般将数据填满一块区域或者触发其他机制会将数据刷新到硬盘上。这块区域就叫缓冲区,机制之一就是flash
FileReader 和 FileWriter
这两个字符流的使用和字节流的使用极为类似,只不过就是字节流的操作单位是字节和字节数组,字符流的操作单位是字符和字符串,甚至方法名和使用都是相同的不过传入的参数类型不同。这里就不在展开
字节流转字符流
我们在这里再介绍两个方法,分别是字节输入流转字符输入流,字节输出流转字符输出流
package www.Zheng;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Scanner;
/**
* @Title: Demo6
* @Author zyh
* @Package www.Zheng
* @Date 2024/7/7 23:29
* @description: 字节输入转换为字符输入的简单实现
*/
public class Demo6 {
public static void main(String[] args) {
try (InputStream stream = new FileInputStream()){
Scanner scanner = new Scanner(stream);
System.out.println(scanner.nextLine());
} catch (FileNotFoundException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
package www.Zheng;
import java.io.*;
import java.util.Scanner;
/**
* @Title: Demo7
* @Author zyh
* @Package www.Zheng
* @Date 2024/7/7 23:39
* @description: 字节输出流转字符输出流
*/
public class Demo7 {
public static void main(String[] args) throws IOException {
try (OutputStream stream = new FileOutputStream()){
PrintWriter writer = new PrintWriter(stream);
writer.printf("哈哈");
writer.flush();
}
}
}
//PrintWriter 类中提供了我们熟悉的 print/println/printf 方法
//同样也有flash方法
结语
以上便是今天的全部内容。如果有帮助到你,请给我一个免费的赞。
因为这对我很重要。
编程世界的小比特,希望与大家一起无限进步。
感谢阅读!