01-IO流(File概述)
接下来说IO包中比较重要的一个对象,也是比较特殊的一个对象:File类。流在操作的只有数据,而数据最明显的体现形式就是文件。而文件又包含了很多属性和行为信息,所以Java中就用File类对文件这类事物进行描述。
File类用于将文件或者文件夹封装成对象,可以操作文件或者文件夹的属性信息。
File类的出现弥补了流的不足。流可以操作文件,但是不能操作文件夹,也不能操作文件和文件夹的属性信息,比如说这个文件是可读还是可写的,流都不知道,流只能操作数据。而想要操作被数据封装成文件的信息,必须用File对象。
接下来看一下File类:
分别用几种构造方法来创建一下File对象:
有一个小问题注意一下:
在Windows系统中文件分隔符是这样的:"\\",但是到了Linux系统中就不是这样了。这句代码到Linux系统中就不适用了。
这时,我们可以用这个分隔符:
这样一来,这句代码就是跨平台的,到了不同系统中都能用:
02-IO流(File对象功能-创建和删除)
接下来我们过一下File类的常见方法。
1,创建文件。
boolean createNewFile();
注意它会抛出异常哦:
代码:
返回为真则代表创建成功:
我们再运行一次,返回值就为假了:
createNewFile的特点是:在指定位置创建文件,如果该文件已经存在,则不创建,返回false。
和输出流不一样,输出流对象一建立创建文件,文件已经存在时,会覆盖。
这里还有创建临时文件的方法:
创建临时文件的意思是,当我们的应用程序在运行的时候,我们利用某些文件来记录这些数据信息,记录完以后这个文件可以被删掉。这个创建临时文件的方法制定了前缀名和后缀名,通常临时文件的名字都是***.temp 。这个我们就不演示了,先做了解即可。
2,删除文件。
第一个方法delete我们就 不讲了,下面直接演示,看看第二个,这个方法叫做退出时删除:
delete演示:
因为前面已经将file.txt文件创建了,所以这里我们将它注释掉,然后写删除语句:
第一次删除返回值为true,第二次删除返回值为false:
但是在实际应用中可能出现这种情况:
程序结束了,但是没有执行最后一句delete语句,所以这个程序还是存在在硬盘上,变成了垃圾文件。
那如果将delete语句放在final中呢?这样也删不掉吗?
也有可能删不掉。
我们平时都有这样的经历,一个文件正在被应用的时候,我们关闭它就会有提示。
一个文件正在被流操作着,它是不能被删掉的。
这时我们就可以用退出时删除这个方法:
它的作用是,告诉虚拟机,我们创建了一个文件,你退出的时候把它删掉哦。这样即使后面程序出现异常,发生中断也没有关系,它依然会被删掉。
一般临时文件会调用这个方法。
总结一下:
delete方法:删除失败返回false。
deleteOnExit方法:在程序退出时删除指定文件。
03-IO流(File对象功能-判断)
3,判断。
判断应用程序是否可以执行此抽象路径名表示的文件:
我们演示一下这个方法:
运行结果为false:
我们换一个已存在的并且可以被应用程序执行的Java文件:
发现返回为true了:
还有此判断是否可以读/写的方法:
我们就不演示了。
按字母顺序比较两个抽象路径名:
这个方法也不做演示了。
测试此抽象路径名表示的文件或目录是否存在:
这个方法用的频率非常高,我们演示一下:
刚刚讲创建文件的时候漏掉了一个方法,就是创建目录:
演示:
程序运行前的当前目录:
程序运行后的当前目录:
我们再试着多一层:
运行之后我们发现abc文件夹中还有一个kkk文件夹:
那这样呢:
我们发现返回结果为false。
因为mkdir方法只可以创建一级目录。
而mkdirs方法则可以创建多级文件夹:
所以只需给刚刚的代码加上s就好了:
补充完创建目录的方法,我们继续回到判断方法中来。
这里有两个发你别判断是否是目录和是否是标准文件的方法:
代码示例:
file.txt是一个文件,但是运行结果两个返回值都是false。原因是file.txt文件根本不存在,而在判断文件对象是否是文件或者目录时,必须要先判断该文件对象封装的内容是否存在。
我们创建一个file.txt文件,然后再运行,发现f.isFile()的返回值就是true了。
我们将刚刚创建的file.txt文件删掉,用它创建一个目录:
这时运行结果中f.isDirectory()返回值为true。
我们去文件夹中看一下,发现果然创建了一个file.txt文件夹:
不过想想也是,没有人规定文件夹名字里不能有txt,所以带后缀的不一定是文件不是目录哦。
判断是否是隐藏文件:
这个方法就不演示了。
判断是否为抽象:
演示:
运行结果为false。
我们修改一下f的路径,使它变成绝对路径:
这样运行结果就是true了。
即使file2.txt这个文件不存在,返回值也为true,因为它只判断整个文件路径是否是绝对路径,和文件存在与否无关。
04-IO流(File对象功能-获取)
4,获取信息。
获取名称:
获取父目录:
获取路径:
获取绝对路径:
注意一下两个方法的区别:
它们都是获取对象的绝对路径,但是第一个方法是将返回的绝对路径封装成了一个File对象,而第二个方法则是返回绝对路径的字符串。
String和File是可以轻松转换的,将String new一下就变成File了,将File toString一下就变成字符串了。
获取最后一次被修改的时间:
获取文件大小:
接下来演示一下。
获取相对路径和绝对路径:
我们发现绝对路径和相对路径是一样的:
因为这个路径本身就是绝对的。
我们重新用一个相对路径试一下:
这样两者返回结果就不同了:
我们封装的是什么路径,getPath方法就会返回给我们什么路径,而getAbsolutePath无论我们封装的是相对的还是绝对的路径,返回来的都是绝对的路径,如果我们封装的是相对的路径,它会给我们这个相对文件前面加上所属的目录。
获取父目录:
这句代码返回值为null。因为我们为f封装的路径是相对路径,它的父目录是不确定的,在不同情况下它的父目录是不同的,所以返回为null。
getParent方法返回的是绝对路径中的父目录,如果获取的是相对路径,返回null。
我们修改一下,将文件的路径写成绝对路径:
这时就拿到了它的父目录:
但是相对路径还有一种情况下返回值不为null:
所以, 如果相对路径中有上一层目录,那么该目录就是返回结果。
获取部分就讲到这里。
下面说一个重命名的方法:
示例:
它的作用是,将c盘下文件名为Test.java的文件重命名,改成hahah.java文件。
将文件名改回Test.java,我们修改一下f2的盘符,改成d。
此时,c盘中存在一个Test.java文件,d盘中不存在hahah.java文件。
运行后,我们发现c盘中的Test.java文件不见了,而d盘中多了一个hahah.java文件,这个hahah.java文件的内容正是原先c盘中Test.java文件中的内容。是不是感觉很玄幻,类似于移动。
05-IO流(File对象功能-文件列表)
我们来看一下这个静态方法:
它不操作具体的特有数据,它操作的是共享数据,所以不用传对象进去。
演示一下这个方法:
它可以列出我们盘符中有效的盘符。
再看这个方法,列出目录中的文件和目录:
示例:
但是要注意,如果f封装的是文件:
就会返回一个空指针异常:
因为list方法所属的对象f是一个文件,没有目录,那么它返回的数组names就是空,为空的话就不能被String name对象指向并遍历。
所以记住,调用list方法的file对象必须是封装了一个目录,该目录还必须存在。
如果目录不存在,运行结果是这样的:
因为它返回数组了,但是数组长度为0。
注意为null和长度为0的不同。
list方法还有一个重载的带参数的:
我们可以使用它,比如要求返回这个目录中所有的.java文件,其他都不要,这样就起到了过滤的作用。
06-IO流(File对象功能-文件列表2)
接下来说说这个带过滤器的list方法,我们点进FilenameFilter中看一看:
它里面只有一个方法,accept:
先要搞一个类把FilenameFilter接口实现一下。
因为list方法中的参数是FilenameFilter接口类型,而且接口中就一个方法,我们可以传一个匿名类。
代码示例:
我们发现还有一个listFiles过滤器:
它和list方法有什么不同呢?
list方法返回的只有当前目录下的文件和文件夹的名称,而listFiles往回返的是当前目录下的文件和文件夹的对象。
代码示例:
07-IO流(列出目录下所有内容-递归)
我们现在有了进一步的想法,不只想获得指定目录下的文件和文件夹,我们还想获得当前目录的子目录下的文件和文件夹,也就是说,想列出指定目录下的所有内容。
我们一步步来,先打印指定目录下的文件和文件夹:
接下来我们想要将制定目录下的子目录中的文件和文件夹也打印出来,这个时候是不是要判断一下files[x]到底是不是文件夹呀?如果是文件夹,就把这个文件夹也传进showDir方法中,获取它里面的内容:
好,现在子目录中的内容也打印出来了:
但是我们发现只打印了文件没有打印目录,很简单,加上这句就好了:
总结一下,因为目录中还有目录,只要使用同一个列出目录功能的函数完成即可。在列出过程中出现的还是目录的话,还可以再次调用本功能。也就是函数自身调用自身,这种表现形式,或者编程手法,称为递归。
递归要注意:
1,限定条件。有限定条件递归才会有终止的时候,没有限定条件递归会陷入无尽的循环。
2,递归次数。尽量避免内存溢出。
08-IO流(列出目录下所有内容-带层次)
之前打印的有点乱,我们想将打印的内容带层次的展示出来。
我们采用加空格的方法:
给原先的代码中加入getLevel调用:
效果大概这样:
哈哈,就是玩一下格式,了解一下就好。
09-IO流(删除带内容的目录)
怎么删除带内容的目录呢?
我们先弄清楚删除的原理:
在Windows中,删除目录时从里面往外删除的。
既然从里面往外删除,就需要用到递归。
示例:
10-IO流(创建java文件列表)
做一个练习:将一个指定目录下的Java文件的绝对路径,存储到一个文本文件中,建立一个Java文件列表文件。
思路:
1,对指定的目录进行递归。
2,获取递归过程中所有的Java文件的路径。
3,将这些路径存储到集合中。
4,将集合中的数据写入到一个文件中。
代码示例:
我们可以看到list集合中存入了220个文件,接下来我们要将这些文件写到文件中去,接下来我们写一个writeToFile方法:
再给主函数中加上这两句:
保存进去啦: