目录
一、什么是文件?
我们一般认为的文件是存在磁盘上的文件,但是从系统的角度上说,一切皆文件,也就是无论是硬件还是软件都可以抽象为文件。
按我们理解的文件又可以分为两大类:普通文件、目录文件(我们常说的文件夹)
在Java标准库中,有一个专门描述文件的类file类,这个类可以帮我们方便的操作文件
在一台主机中,一个文件对应着一个唯一的路径,通过这个路径可以找到这个文件。
/叫做斜杠 \叫做反斜杠,英文名为pathSeparator,作用是分割不同层级的目录
在Windows中既可以使用\作为目录的分隔符,也可以使用/来分割
在Linux或者Mac中,一般使用/来作为路径之间的分隔符
二、绝对路径和相对路径
在实际开发中,表示一个路径,通常两种方式:
1.绝对路径:C:\Program Files\Java\jdk1.8.0_1
以一个盘符开头的路径,这种就是绝对路径
2.相对路径:一般是以.或者是以..开头,有一个基准目录(工作目录),以工作目录为基准,去找到对应的路径
如果要以C:\Program Files\Java\jdk1.8.0_192为基准目录,此时要表示bin
相对路径就可以写作.\bin,.表示当前的基准目录
如果基准目录不一样,相对路径的写法也会不一样
C:\Program Files\Java为基准目录,此时要表示bin
相对路径写作 .\jdk1.8.0_192\bin,.表示当前的基准目录
C:\Program Files\Java\jdk1.8.0_192\jre作为基准目录,此时还是要表示bin
那么应该写作..\bin,..表示当前目录的上级目录
三、throws IOException
在一些访问IO操作,比如读写文件、操作文件的时候,都可能会涉及到这个异常
这个异常是一个受查异常
在使用的时候一定要显示处理
1.throws在函数这里申明
2.try catch来显示捕获
import java.io.File;
import java.io.IOException;
public class TestFile1 {
public static void main(String[] args) throws IOException {
//再执行路径的时候,虽然系统支持\的写法,但是由于在Java中,\+其他字符会被当成转义字符
//因此需要对\进行转义,即写为\\
//或者可以直接写为/,这样就不用进行转义了
//决定路径
File file1=new File("d:/text/path/apple");
System.out.println(file1.getParent());//返回此文件的上一级目录
System.out.println(file1.getName());//返回这个文件的文件名
System.out.println(file1.getPath());//返回这个文件的路径
System.out.println(file1.getAbsolutePath());//返回这个文件的绝对路径
System.out.println(file1.getCanonicalPath());//返回这个文件的绝对路径
System.out.println(file1.exists());//看这个文件在d盘中到底在不在
//相对路径
File file2=new File("./apple");
System.out.println(file2.getParent());//返回此文件的上一级目录
System.out.println(file2.getName());//返回这个文件的文件名
System.out.println(file2.getPath());//返回这个文件的路径
System.out.println(file2.getAbsolutePath());//返回这个文件的绝对路径
System.out.println(file2.getCanonicalPath());//返回这个文件的绝对路径
System.out.println(file2.exists());//看这个文件在d盘中到底在不在
}
}
运行结果为:
注意这两者的差别,他们在上述的运行结果中已经能够说明问题,即getAbsolutePath()方法显示的是我们输入的和它本来所在的目录,也就是没有经过简化的,而getCanonicalPath()显示的是getAbsolutePath()的结果简化过的。
还有一个要注意的地方是我们输入目录时是/,而输出的结果却是\,原因是在Windows上默认是使用\作为目录之间的分隔符的,虽然Windows也支持/,但是在代码内部一般都是用\来表示。
在IDEA中我们直接运行一个程序,此时的工作目录就是当前项目所在的目录
在代码中涉及到的相对路径,以当前项目所在的目录作为基准
代码除了在IDEA中运行,还可以通过命令行的方式运行
如果是通过命令行的方式运行,当前命令行所在的目录就是工作路径
上述红圈中的文件,既没有盘符,也没有./和..//,这个叫做相对路径,此处是相当于省略了./。
上面的代码运行结果为
四、创建文件为啥会抛异常?
这意味着文件可能会创建失败,常见的原因有两个 ,第一是没有权限,文件系统中典型的权限有读、写和可执行权限,系统会根据不同的用户给出不同的权限,第二就是磁盘空间不够了。
public class TestFile3 {
public static void main(String[] args) throws IOException, InterruptedException {
File file=new File("helloWorld.txt");
file.createNewFile();
Thread.sleep(3000);
System.out.println(file.delete());
}
}
这个代码的运行结果返回值为布尔类型,要想看到完整的创建文件和删除文件的过程,那么操作为第一步:
第二步和第三步
第四步
点击第三步后会出现和以下的类似的页面,这个时候就可以观察到文件的创建和删除过程了
import java.io.File;
import java.io.IOException;
public class TestFile4 {
public static void main(String[] args) throws IOException, InterruptedException {
File file=new File("helloWorld.txt");
file.createNewFile();
System.out.println("文件创建成功");
Thread.sleep(3000);
file.deleteOnExit();
System.out.println("文件退出即删除");
Thread.sleep(3000);
}
}
运行结果为
具体的过程可以用上一个代码的方法看
五、file.deleteOnExit()
这个方法主要是用于一些临时文件
在使用Word或者Excel的时候,打开文件的时候,系统会同时生成一个临时的隐藏文件,当把Word或者Excel关闭的时候,临时文件就自动删除了。
这个功能是很有用的,比如我们在台式电脑上写论文时突然间停电了,由于没保存的数据在内存中,如果没电了,那么内存中的数据就丢失了,我们刚刚写的内容就白写了,Office采取的机制是在用户编辑的时候创建临时文件,没保存的内容都会存进这个临时文件中,如果突然掉电了,虽然内存中的数据丢失了,但是临时文件里面相当于还有一个备份,此时就可以通过临时文件把数据恢复过来。
那么为什么临时文件还存在呢?上面不是说当把Word或者Excel关闭的时候,临时文件就自动删除了吗?原因是这样的,当在正常情况下,Word或者Excel关闭的时候,临时文件确实是自动删除了,但是在突然掉电关机的情况下,临时文件是来不及删除的,当下次启动的时候,office就会自动检测到当前临时文件的存在,于是就可以知道上次是异常结束,就会提示用户是否要恢复数据。
六、list()方法
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
public class TestFile5 {
public static void main(String[] args) throws IOException {
File file=new File(".");
File file1=new File("helloWorld");
file1.createNewFile();
String[] files=file.list();
System.out.println(Arrays.toString(files));
}
}
运行结果
七、隐藏文件
隐藏文件是由$修饰的,一般是看不到的,不过通过修改一些选项就可以看到
这样设置后,隐藏的文件就可以看见了
八、经典面试题
给一个list方法,遍历一个目录中的所有文件(包含子目录中的文件)
import java.io.File;
import java.util.ArrayList;
import java.util.List;
//面试题
//通过递归的方式来罗列出目录中所有的文件路径
public class TestFile6 {
public static List<String> result=new ArrayList<>();
public static void getAllFiles(String basePath){
File file=new File(basePath);
if (file.isFile()) {
result.add(basePath);
return;
} else if (file.isDirectory()) {
for (String s: file.list()) {
getAllFiles(basePath+"/"+s);
}
}else {
//这类文件既不是普通文件也不是目录,暂时不考虑
//这类文件确实存在,只是现在暂时不考虑,
//这类文件是socket文件、管道文件、设备块文件......
}
}
public static void main(String[] args) {
getAllFiles(".");
for (String s:result) {
System.out.println(s);
}
}
}
这道面试的核心思路就是利用递归解。
九、mkdir()方法和mkdirs()方法
import java.io.File;
public class FileDemo7 {
public static void main(String[] args) {
/*File file=new File("hello");
System.out.println(file.exists());
//mk为make的缩写,dir是direction的缩写
file.mkdir();*/
File file=new File("hello/aaa/bbb");
System.out.println(file.exists());
//mkdir不支持创建多级目录,但是mkdirs支持
file.mkdirs();
System.out.println(file.exists());
System.out.println(file.isDirectory());
}
}
运行结果为
创建的多级目录可以利用上面提到过的四个步骤看出,创建的目录为
十、renameTo()方法
renameTo不仅可以修改文件名,还可以更改文件的路径(把一个文件从一个目录中移动到另一个目录中)
1.修改文件名
import java.io.File;
import java.io.IOException;
public class FileDemo8 {
public static void main(String[] args) throws IOException {
File file1=new File("home.txt");
file1.createNewFile();
File file3=new File("hello.txt");
//File file2=new File("./out/home");
//renameTo不仅可以修改文件名,还可以更改文件的路径
System.out.println(file1.renameTo(file3));
}
}
运行结果为
2.修改路径
这个操作就相当于是截切粘贴
import java.io.File;
import java.io.IOException;
public class FileDemo8 {
public static void main(String[] args) throws IOException {
File file1=new File("hello.txt");
//file1.createNewFile();
File file3=new File("./out/hello.txt");
//File file2=new File("./out/home");
//renameTo不仅可以修改文件名,还可以更改文件的路径
System.out.println(file1.renameTo(file3));
}
}
运行结果为
十一、文件移动和文件复制
所谓的文件移动(截切粘贴),对于操作系统来说,是一个非常高效的操作
每个文件都有个属性,这个属性就是这个文件的路径,移动操作其实就是修改了一下文件的属性而已,但是如果是把文件跨硬盘来移动,这个时候就很低效了。
所谓的文件复制(复制粘贴),对于操作系统来说,可能是一个非常低效的操作
它需要把文件的内容都读出来,拷贝一份,再写入磁盘中,当文件很大时,开销就比较大了。