上期我们彻底学完多线程啦,接下来的内容暂时轻松一点,我们要学习对文件的操作;
文件操作和IO
1,认识文件
什么是文件呢,文件分为广义的文件和狭义的文件;
狭义的文件指保存在硬盘上的文件;
广义的文件指操作系统进行资源管理的一种机制,很多的软件或者硬件资源抽象成“文件”来表示;
我们今天主要讨论狭义的文件,
我们使用计算机的时候通常管这个叫文件夹,这个这个不是专业的叫法这个是目录(directory);
里面有目录或者是文件,也可以为空,它还有一些除了内容以外的信息:
1)树形结构组织 和 目录
文件的引出带来了很大的便利,但是随着文件的内容越来越多,我们怎么管理这些文件呢,我们也不能直接把这些文件堆在一堆呀,我们就使用了树形结构来存储我们的文件,
我们看这个java地面知识点;
一个目录包含很多目录,我们找到其中一个目录,并进入到这个目录,我们还能看到很多目录,就像我们学习的多叉树一样;
2)文件路径(Path)
这么复杂的结构,那么我们是怎么准确搜索到我们要找到的文件呢,比如刚才的图片,算了我们新弄一个图片
我们在当前路径中放了一个新的图片,
"C:\cctalk\java代码容易犯错的知识点\QQ截图20240915161600.png"
我们复制文件的地址,这个就是当前图片的绝对路径,什么是绝对路径呢,就从从c盘开始,直接到当前文件的所有路径;
除此之外还有相对路径,相对路径需要描述一个基准路径,什么是基准路径呢,我们在用基准路径找一下这张图片:
基准路径: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(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() | 根据File对象,标注文件将要被删除,删除不会立即执行,删除动作会在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());
这个呢,就是我们给的绝对路径和相对路径中不存在的test.txt,我们会把它创建出来;
这时java知识点中就出现了对应的文件:
我们再试试两个删除操作
File file = new File("C:/cctalk/java代码容易犯错的知识点/test.txt");
System.out.println(file.delete());
删掉了;那么第二个删除操作是怎么样的,再jvm运行结束时删除怎么看到呀,我们来试试:
先创建出来,
File file = new File("C:/cctalk/java代码容易犯错的知识点/test.txt");
file.deleteOnExit();
while (true){
Thread.sleep(100);
System.out.println(111);
}
来运行:
这时候看,主线程是在阻塞,我们看我们的test.txt文件发现是没有删除的;
我们结束代码:
这个文件就被删掉了;
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());
我们看到即使我们没有demo3这一目录我们也成功创建了,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);
把hhhh移动过来了;
还剩两个方法一个是canRead(),另一个是canWirte();
这个就是看用户有没有读和写的权限;
File file = new File("C:/cctalk/java代码容易犯错的知识点/Demo/demo2/demo3/hhhh");
System.out.println(file.canRead());
System.out.println(file.canWrite());
读和写权限都有,那么我们怎么知道我们是否有读还是写的权限呢?
我们看到hhhh这里有这4个:
我们的canRead和canWrite就是这4个权限的并集,也就是说有一个有读权限canRead就有权限,write也一样;
下期带来文件内容操作;