Java基础里文件输入输出的初步探索(其一)
上一回我们已经把多线程彻底学完啦,接下来的内容会轻松一些,我们要开始研究文件的相关操作啦;
文件操作与IO
1,认识文件
那究竟什么是文件呢?文件有广义和狭义之分;
狭义的文件指的是存储在硬盘上的那些文件;
广义的文件是操作系统进行资源管理的一种机制,很多软件或者硬件资源都被抽象成“文件”来进行表示;
我们今天主要探讨的是狭义的文件,

我们在使用计算机的时候通常把这个叫做文件夹,但这不是专业的叫法,专业点叫目录(directory);
目录里面可以有其他目录或者文件,也有可能是空的,它还有一些除了内容之外的信息:

1)树形结构组织与目录
文件的出现带来了很大的便利,不过随着文件内容越来越多,我们得怎么管理这些文件呢?总不能把所有文件堆在一起吧,于是我们采用树形结构来存储文件,

看看这个java相关的知识点;

一个目录包含好多子目录,我们找到其中一个目录并进入,还能看到更多目录,就像我们学过的多叉树一样;
2)文件路径(Path)
这么复杂的结构,那我们怎么精准找到想要的文件呢?比如刚才的图片,算了,我们换个新图片

我们在当前路径下放了一张新图片,
“C:\cctalk\java代码容易犯错的知识点\QQ截图20240915161600.png”
我们复制这个文件的地址,这就是当前图片的绝对路径,绝对路径就是从根目录开始,一直到当前文件的完整路径;
除此之外还有相对路径,相对路径需要有一个基准路径,那基准路径是什么呢?我们用基准路径来找这张图片:
基准路径:C:\cctalk
这时候有了基准,我们找这张图片只需要:
.\java代码容易犯错的知识点\QQ截图20240915161600.png
就能找到它啦,.表示当前目录,..表示父目录,但不能去爷爷目录,也就是父目录的父目录,
有了路径,我们就能轻松找到想要的数据啦;
3)知识补充
我们来聊聊文件的种类,文件分为二进制文件和文本文件;
冯诺依曼祖师爷定过规矩,所有文件本质上都是二进制的,计算机组成原理里讲过,因为0和1的组合好控制,有些文件的二进制数据刚好能构成字符,大家还记得一个汉字占几个字节吗,别瞎答哦,utf8是3个字节,utf16是2个字节,utf32是4个字节,还有其他编码方式,文本文件就是二进制文件通过查码表转换成文本内容;
图片、视频、音乐以及可执行程序等都是二进制文件,而java.c、Txt纯文本属于文本文件,像word、docx(富文本)也都是二进制文件;
还有dll是动态库,通常作为文件后缀存在;
2,java中的文件操作
接下来我们讲讲java里的文件操作,分为文件系统操作和文件内容操作;
文件系统操作比如创建目录、创建文件、删除和重命名等;
文件内容操作就是对文件内容进行修改;
这里主要讨论文件系统操作;
1)File概述
java通过java.io.File来描述文件(目录),不过存在创建了File对象但对应的文件不存在的情况;
1> 属性
修饰符及类型 | 属性 | 说明 |
---|---|---|
static String |
pathSeparator |
路径列表分隔符 (如 : 在 Linux/macOS,; 在 |
Windows),用于分隔多个路径(如 PATH 环境变量)。 |
||
static char |
pathSeparatorChar |
同上,但以 char 类型表示。 |
static String |
separator |
文件路径分隔符 (如 / 在 Linux/macOS,\ 在 |
Windows),用于分隔目录层级。 | ||
static char |
separatorChar |
同上,但以 char 类型表示。 |
这是啥意思呢,我刚学的时候也不太明白,为啥分字符串和字符呢,我们写代码时常用/或者转义\\两个斜杠,不同操作系统可能不一样,用pathSeparator和separator能提高代码跨平台兼容性;
public class Demo {
public static void main(String[] args) {
// 输出路径列表分隔符(如 ; 或 :)
System.out.println("Path Separator: " + File.pathSeparator); // String
System.out.println("Path Separator Char: " + File.pathSeparatorChar); // char
// 输出文件路径分隔符(如 \ 或 /)
System.out.println("File Separator: " + File.separator); // String
System.out.println("File Separator Char: " + File.separatorChar); // char
}
}

属性分字符串和字符,字符串方便拼接,字符更底层适合遍历;
2> 构造方法
签名 | 说明 |
---|---|
File(String Parent,String child ) | 根据父目录(非路径)+子文件夹路径构建新的File实例 |
File(String pathname) | 根据文件路径创建File实例,可绝对路径或相对路径 |
File(File parent,String child) | 根据父目录路径+子文件夹路径构建新的File实例 |
3> 方法
修饰符及返回值类型 | 方法签名 | 说明 |
---|---|---|
String | getParent() | 返回File对象的父目录文件路径 |
String | getName() | 返回File对象的纯文件名称 |
String | getPath() | 返回File对象的文件路径 |
String | getAbsolutePath() | 返回File对象的绝对路径 |
String | getCanonicalPath() | 返回File对象的规范绝对路径 |
我们来试一下:
先试试绝对路径——
File file = new File("C:"+ File.separator+"ctalk/java代码容易犯错的知识点/test.txt");
System.out.println(file.getParent());
System.out.println(file.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsoluteFile());
System.out.println(file.getCanonicalFile());
运行:

再试试相对路径:
File file = new File("./java代码容易犯错的知识点/test.txt");
System.out.println(file.getParent());
System.out.println(file.getName());
System.out.println(file.getPath());
System.out.println(file.getAbsoluteFile());
System.out.println(file.getCanonicalFile());
boolean | exists() | 判断File对象描述的文件是否真实存在 |
---|---|---|
boolean | isDirectory() | 判断File对象代表的文件是否是目录 |
boolean | isFile() | 判断File对象代表的文件是否是普通文件 |
boolean | createNewFile() | 根据File对象自动创建空文件,成功返回true |
boolean | delete() | 根据File对象删除文件,成功返回true |
void | deleteOnExit() | 标注文件将被删除,删除在JVM运行结束后执行 |
来试试:
File file = new File("C:/cctalk/java代码容易犯错的知识点/test.txt");//此时test.txt不存在;
System.out.println(file.exists());//判断是否存在
不存在;
再创建文件:
File file = new File("C:/cctalk/java代码容易犯错的知识点/test.txt");
System.out.println(file.exists());

存在了;
File file = new File("C:/cctalk/java代码容易犯错的知识点/test.txt");
System.out.println(file.isDirectory());//判断是否为目录
System.out.println(file.isFile());//判断是否为文件

我们创建的是文件test.txt;
试试目录:
File file = new File("C:/cctalk/java代码容易犯错的知识点");
System.out.println(file.isDirectory());
System.out.println(file.isFile());

ok;
用file创建文件:
File file = new File("C:/cctalk/java代码容易犯错的知识点/test.txt");
System.out.println(file.createNewFile());
会创建出对应的文件;
再试试删除操作:
File file = new File("C:/cctalk/java代码容易犯错的知识点/test.txt");
System.out.println(file.delete());


删掉了;那删除OnExit呢,看看:

先创建文件,
File file = new File("C:/cctalk/java代码容易犯错的知识点/test.txt");
file.deleteOnExit();
while (true){
Thread.sleep(100);
System.out.println(111);
}
运行时看文件没删;

结束代码后文件被删;
String[] | list() | 返回File对象代表目录下的所有文件名 |
---|---|---|
File[] | listFiles() | 返回File对象代表目录下的所有文件,以File对象表示 |
boolean | mkdir() | 创建File对象代表的目录 |
boolean | mkdirs() | 创建File对象代表的目录,必要时创建中间目录 |
boolean | renameTo(File dest) | 重命名文件,也可视为剪切粘贴 |
boolean | canRead() | 判断用户是否有读权限 |
boolean | canWrite() | 判断用户是否有写权限 |

在这里创建Demo,在Demo里创建一些文件

把它们列出来:
File file = new File("C:/cctalk/java代码容易犯错的知识点/Demo");
String[] str = file.list();
for (String a: str){
System.out.println(a);
}

用listFiles:
File file = new File("C:/cctalk/java代码容易犯错的知识点/Demo");
File[] files = file.listFiles();
for (File a:files){
System.out.println(a);
}

mkdir()和mkdirs()是创建目录的方法;
mkdir()必须父目录存在才能创建,不会自动创建父目录;
File file = new File("C:/cctalk/java代码容易犯错的知识点/Demo/demo2");
System.out.println(file.mkdir());

创建demo2;
mkdirs():
File file = new File("C:/cctalk/java代码容易犯错的知识点/Demo/demo2/demo3/demo4");
System.out.println(file.mkdirs());


即使父目录不存在也能创建,会自动创建目录;
renameTo方法,能重命名文件,也能移动文件,本质是用新File代替旧File;

把test文件夹改名hhhh:
File oldfile = new File("C:/cctalk/java代码容易犯错的知识点/Demo/demo2/demo3/demo4/test.txt");
File newfile = new File("C:/cctalk/java代码容易犯错的知识点/Demo/demo2/demo3/demo4/hhhh");
oldfile.renameTo(newfile);

移动到demo3:
File oldfile = new File("C:/cctalk/java代码容易犯错的知识点/Demo/demo2/demo3/demo4/hhhh");
File newfile = new File("C:/cctalk/java代码容易犯错的知识点/Demo/demo2/demo3/hhhh");
oldfile.renameTo(newfile);

最后两个方法canRead()和canWrite(),看用户是否有读写权限;
File file = new File("C:/cctalk/java代码容易犯错的知识点/Demo/demo2/demo3/hhhh");
System.out.println(file.canRead());
System.out.println(file.canWrite());

有读写权限,这四个权限组合起来就是canRead和canWrite的判断依据;
下期讲解文件内容操作;