java I/O系统(1)-File类

引言

自己对java的IO系统不是非常了解。所以我想进一步一点点去整理好它。在本篇博文中,我们详细介绍一下File类的意义,包括它很大部分的功能。笔者目前整理的一些blog针对面试都是超高频出现的。大家可以点击链接:http://blog.csdn.net/u012403290

技术点

1、绝对路径和相对路径
我们用一张图来理解两种路径的概念:
这里写图片描述

绝对路径是指从根部开始,直到到达目的文件,比如在上图中,用绝对路径表示user.java文件,那么我们就需要这样:F:/java/io/user.java
或者,甚至可以不包括盘符,比如说上面我们可以直接描述成/java/io/user.java
我们用代码验证上面所说的绝对路径:

import java.io.File;

public class PathTest {

    public static void main(String[] args) {
        File file = new File(args[0]);
        System.out.println(file.exists());
    }

}

测试代码就是如上这段代码,可以根据测试情景,把它放到对于的地方,我把它放在了io文件加下,与user.java同级别。以下是测试结果:
这里写图片描述
这里我要说明一点,在java中不能单纯的用“\”来表示文件级别,因为在java中它是一种转义符,但是可以用“\”来表示。但是用“/”可以表示文件级别。总之,意思就是F:\java\io\user.java和F:/java/io/user.java是一样的。
再者,注意特殊的不带盘符号的绝对路径的使用,需要考量你所处的盘,你在C盘任意地方运行上述测试代码,得到的应该是false、true。但是你在F盘任意地方运行得到的结果是true 、true。

相对路径是指从当前路径开始,“相对”意思肯定是需要对什么进行比较,所以可以理解为相对于操作人自身处于文件系统的位置。
比如说,你现在在java文件目录下,那么用相对路径表示user.java文件,就是这样:io/user.java
更严格来说,我们用“.”表示当前路径,所以更应该描述成这样:./io/user.java
但是如果你本身在go文件目录下的时候,如何用相对路径来表示user.java文件呢?这个时候就需要把文件目录往上跳一级,“..”表示父级目录,那么我们就可以描述成:../java/io/user.java

我们把上面的测试demo放入java文件夹目录,测试结果如下:
这里写图片描述

接着,我们把测试demo放入go文件目录下,测试结果如下:
这里写图片描述

关于绝对路径和相对路径就介绍到这里。

2、File类
它是一个实用的类库工具,可以帮助我们处理文件目录问题。我们不要被file名字所误导。它可以表示指定的文件,也可以表示一个目录下的所有文件。在后面,我们会对它关键方法进行逐一测试实用,熟练掌握这些,将会是深入学习IO系统的基础。

在File类中,我将要归纳如下这些方法:

创建方法:
1、boolean createNewFile(): 当且仅当不存在具有此抽象路径名指定名称的文件时,不可分地创建一个新的空文件。
2、 boolean mkdir() : 创建此抽象路径名指定的目录。
3、 boolean mkdirs() : 创建此抽象路径名指定的目录,包括所有必需但不存在的父目录。

删除方法:
1、 boolean delete(): 删除此抽象路径名表示的文件或目录。
2、void deleteOnExit():在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。

判断方法:
1、boolean canExecute() : 测试应用程序是否可以执行此抽象路径名表示的文件。
2、boolean canRead() :测试应用程序是否可以读取此抽象路径名表示的文件。
3、boolean canWrite() :测试应用程序是否可以修改此抽象路径名表示的文件。
4、boolean exists() : 测试此抽象路径名表示的文件或目录是否存在。
5、boolean isAbsolute() : 测试此抽象路径名是否为绝对路径名。
6、boolean isDirectory() :测试此抽象路径名表示的文件是否是一个目录。
7、boolean isFile() :测试此抽象路径名表示的文件是否是一个标准文件。
8、boolean isHidden() :测试此抽象路径名指定的文件是否是一个隐藏文件。

获取方法:
1、long lastModified() : 返回此抽象路径名表示的文件最后一次被修改的时间。
2、long length() :返回由此抽象路径名表示的文件的长度。
3、String getAbsolutePath() :返回此抽象路径名的绝对路径名字符串。
5、long getFreeSpace() :返回此抽象路径名指定的分区中未分配的字节数。
6、String getName() :返回由此抽象路径名表示的文件或目录的名称。
7、String getParent() :返回此抽象路径名父目录的路径名字符串;如果此路径名没有指定父目录,则返回 null。
8、String getPath() :将此抽象路径名转换为一个路径名字符串。
9、long getTotalSpace() :返回此抽象路径名指定的分区大小。
10、long getUsableSpace() :返回此抽象路径名指定的分区上可用于此虚拟机的字节数。
11、String[] list() :返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中的文件和目录。
12、String[] list(FilenameFilter filter) :返回一个字符串数组,这些字符串指定此抽象路径名表示的目录中满足指定过滤器的文件和目录。

代码功能测试:

1、测试创建和删除方法

package com.brickworkers.io;

import java.io.File;
import java.io.IOException;

public class PathTest {

    public static void main(String[] args) throws IOException {
        //3个创建方法
        File file1 = new File("F:/java/io/admin.java");
        if(!file1.exists()){
            file1.createNewFile();
        }

        File file2 = new File("F:/java/io/mkdir");
        if(!file2.exists()){
            file2.mkdir();
        }

        File file3 = new File("F:/python/io/mkdirs");
        if(!file3.exists()){
            file3.mkdirs();
        }
        file1.delete();
        file2.deleteOnExit();
        System.out.println(file1.exists());
        System.out.println(file2.exists());
    }

}
//输出结果:
//false
//true



测试结果显示:createNewFile会创建一个具体的空文件,而mkdir和mkdirs会创建文件夹。那么mkdir与mkdirs有什么区别呢?mkdir创建文件夹必须要在上级文件夹都存在的情况下进行创建,也就是说在例子中创建mkdr文件夹的时候,那么它的上级java/io是必须存在的,不然就返回false。而mkdirs如果上级文件夹不存在,那么它会一并创建。
两个删除功能,delete和deleteOnExit。前者是直接删除文件,后者是等待程序执行完毕之后删除文件。也就是说,程序运行deleteOnExit成功后,File并没有直接删除,而是在虚拟机正常运行结束后才会删除。使用场景一般是处理临时文件,我们要求这个文件在程序执行结束之后才删除。所以,在上面的代码中输出的是false和true

2、测试判断方法:
为了测试判断方法,我创立了4个文件,其中3个是具体的文件,一个是目录,如下图:
这里写图片描述
其中hidden.txt我把它属性设置为隐藏,read.txt设置为只读。同时用代码再创建一个相对路径下的文件。详细代码如下:

package com.brickworkers.io;

import java.io.File;
import java.io.IOException;

public class PathTest {

    public static void main(String[] args) throws IOException {
        //判断方法
        File read = new File("F:/java/io/read.txt");
        File hidden = new File("F:/java/io/hidden.txt");
        File write = new File("F:/java/io/write.txt");
        File directory = new File("F:/java/io/directory");
        //创建一个相对路径的文件
        File testFile = new File("./test.txt");
        if(!testFile.exists()){
            testFile.createNewFile();
        }

        //文件是否存在
        System.out.println("read文件是否存在:" + read.exists());
        System.out.println("hidden文件是否存在:" + hidden.exists());
        System.out.println("write文件是否存在:" + write.exists());
        System.out.println("directory文件是否存在:" + directory.exists());
        System.out.println("testFile文件是否存在:" + testFile.exists());
        System.out.println("===============================================");
        //是否隐藏
        System.out.println("read文件是否隐藏:" + read.isHidden());
        System.out.println("hidden文件是否隐藏:" + hidden.isHidden());
        System.out.println("write文件是否隐藏:" + write.isHidden());
        System.out.println("directory文件是否隐藏:" + directory.isHidden());
        System.out.println("testFile文件是否隐藏:" + testFile.isHidden());
        System.out.println("===============================================");
        //是否可读
        System.out.println("read文件是否可读:" + read.canRead());
        System.out.println("hidden文件是否可读:" + hidden.canRead());
        System.out.println("write文件是否可读:" + write.canRead());
        System.out.println("directory文件是否可读:" + directory.canRead());
        System.out.println("testFile文件是否可读:" + testFile.canRead());
        System.out.println("===============================================");
        //是否可写
        System.out.println("read文件是否可写:" + read.canWrite());
        System.out.println("hidden文件是否可写:" + hidden.canWrite());
        System.out.println("write文件是否可写:" + write.canWrite());
        System.out.println("directory文件是否可写:" + directory.canWrite());
        System.out.println("testFile文件是否可写:" + testFile.canWrite());
        System.out.println("===============================================");
        //是否目录
        System.out.println("read文件是否目录:" + read.isDirectory());
        System.out.println("hidden文件是否目录:" + hidden.isDirectory());
        System.out.println("write文件是否目录:" + write.isDirectory());
        System.out.println("directory文件是否目录:" + directory.isDirectory());
        System.out.println("testFile文件是否目录:" + testFile.isDirectory());
        System.out.println("===============================================");
        //是否标准文件
        System.out.println("read文件是否标准文件:" + read.isFile());
        System.out.println("hidden文件是否标准文件:" + hidden.isFile());
        System.out.println("write文件是否标准文件:" + write.isFile());
        System.out.println("directory文件是否标准文件:" + directory.isFile());
        System.out.println("testFile文件是否标准文件:" + testFile.isFile());
        System.out.println("===============================================");
        //是否绝对路径
        System.out.println("read文件是否绝对路径:" + read.isAbsolute());
        System.out.println("hidden文件是否绝对路径:" + hidden.isAbsolute());
        System.out.println("write文件是否绝对路径:" + write.isAbsolute());
        System.out.println("directory文件是否绝对路径:" + directory.isAbsolute());
        System.out.println("testFile文件是否绝对路径:" + testFile.isAbsolute());
        System.out.println("===============================================");
        //判断文件是否可执行
        System.out.println("read文件是否可执行:" + read.canExecute());
        System.out.println("hidden文件是否可执行:" + hidden.canExecute());
        System.out.println("write文件是否可执行:" + write.canExecute());
        System.out.println("directory文件是否可执行:" + directory.canExecute());
        System.out.println("testFile文件是否可执行:" + testFile.canExecute());

    }

}

//执行结果:
//read文件是否存在:true
//hidden文件是否存在:true
//write文件是否存在:true
//directory文件是否存在:true
//testFile文件是否存在:true
//===============================================
//read文件是否隐藏:false
//hidden文件是否隐藏:true
//write文件是否隐藏:false
//directory文件是否隐藏:false
//testFile文件是否隐藏:false
//===============================================
//read文件是否可读:true
//hidden文件是否可读:true
//write文件是否可读:true
//directory文件是否可读:true
//testFile文件是否可读:true
//===============================================
//read文件是否可写:false
//hidden文件是否可写:true
//write文件是否可写:true
//directory文件是否可写:true
//testFile文件是否可写:true
//===============================================
//read文件是否目录:false
//hidden文件是否目录:false
//write文件是否目录:false
//directory文件是否目录:true
//testFile文件是否目录:false
//===============================================
//read文件是否标准文件:true
//hidden文件是否标准文件:true
//write文件是否标准文件:true
//directory文件是否标准文件:false
//testFile文件是否标准文件:true
//===============================================
//read文件是否绝对路径:true
//hidden文件是否绝对路径:true
//write文件是否绝对路径:true
//directory文件是否绝对路径:true
//testFile文件是否绝对路径:false
//===============================================
//read文件是否可执行:true
//hidden文件是否可执行:true
//write文件是否可执行:true
//directory文件是否可执行:true
//testFile文件是否可执行:true

其余的内容大家都可以理解。但是注意最后一个判断方法:canExecute。这个方法怎么返回的都是true。但是这个方法的功能是判断文件是否可执行,我用好多的文件测试都是true。后来,我再linux上进行尝试,创建了2个文件,一个是可以执行的,一个是不可执行的:
这里写图片描述

测试代码如下:
这里写图片描述

测试结果如下:
这里写图片描述

3、测试获取方法
在原先文件的基础上,我在write.txt文件中加入了一些内容。同时,我在directory文件夹目录下加了4个文件,分别是file1.txt、file2.txt、file3.txt、file4.txt。

package com.brickworkers.io;

import java.io.File;
import java.io.IOException;

public class FileTest {
    public static void main(String[] args) throws IOException {
        File write = new File("F:/java/io/write.txt");
        File directory = new File("F:/java/io/directory");
        File read = new File("F:/java/io/read.txt");

        //创建一个绝对路径的文件
        File testFile = new File("./testFile.txt");
        if(!testFile.exists()){
            testFile.createNewFile();
        }

        //获取最后修改时间
        System.out.println("write最后修改时间" + write.lastModified());
        System.out.println("directory最后修改时间" + directory.lastModified());
        System.out.println("read最后修改时间" + read.lastModified());
        System.out.println("testFile最后修改时间" + testFile.lastModified());
        System.out.println("====================================================");

        //获取文件长度
        System.out.println("write文件长度" + write.length());
        System.out.println("directory文件长度" + directory.length());
        System.out.println("read文件长度" + read.length());
        System.out.println("testFile文件长度" + testFile.length());
        System.out.println("====================================================");

        //获取绝对路径
        System.out.println("write文件的绝对路径" + write.getAbsolutePath());
        System.out.println("directory文件的绝对路径" + directory.getAbsolutePath());
        System.out.println("read文件的绝对路径" + read.getAbsolutePath());
        System.out.println("testFile文件的绝对路径" + testFile.getAbsolutePath());
        System.out.println("====================================================");


        //获取名称
        System.out.println("write文件的名称" + write.getName());
        System.out.println("directory文件的名称" + directory.getName());
        System.out.println("read文件的名称" + read.getName());
        System.out.println("testFile文件的名称" + testFile.getName());
        System.out.println("====================================================");
        //获取父文件夹名称
        System.out.println("write文件父文件夹的名称" + write.getParent());
        System.out.println("directory文件父文件夹的名称" + directory.getParent());
        System.out.println("read文件父文件夹的名称" + read.getParent());
        System.out.println("testFile文件父文件夹的名称" + testFile.getParent());
        System.out.println("====================================================");

        //获取抽象名的路径
        System.out.println("write文件路径" + write.getPath());
        System.out.println("directory文件路径" + directory.getPath());
        System.out.println("read文件路径" + read.getPath());
        System.out.println("testFile文件路径" + testFile.getPath());
        System.out.println("====================================================");

        //获取总容量大小
        System.out.println("write文件容量大小" + write.getTotalSpace()/(1024*1024*1024) + "g");
        System.out.println("directory文件容量大小" + directory.getTotalSpace()/(1024*1024*1024) + "g");
        System.out.println("read文件容量大小" + read.getTotalSpace()/(1024*1024*1024) + "g");
        System.out.println("testFile文件容量大小" + testFile.getTotalSpace()/(1024*1024*1024) + "g");
        System.out.println("====================================================");


        //获取未使用的容量大小
        System.out.println("write文件剩余容量大小" + write.getFreeSpace()/(1024*1024*1024) + "g");
        System.out.println("directory文件剩余容量大小" + directory.getFreeSpace()/(1024*1024*1024) + "g");
        System.out.println("read文件剩余容量大小" + read.getFreeSpace()/(1024*1024*1024) + "g");
        System.out.println("testFile文件剩余容量大小" + testFile.getFreeSpace()/(1024*1024*1024) + "g");
        System.out.println("====================================================");


        //获取文件名称数组
        System.out.println("write文件下文件" + write.list());
        System.out.println("directory文件下文件" + directory.list());
        System.out.println("read文件下文件" + read.list());
        System.out.println("testFile文件下文件" + testFile.list());

    }

}

//测试结果:
//write最后修改时间1494405362038
//directory最后修改时间1494405719942
//read最后修改时间1494402367012
//testFile最后修改时间1494406191698
//====================================================
//write文件长度1909600
//directory文件长度0
//read文件长度0
//testFile文件长度0
//====================================================
//write文件的绝对路径F:\java\io\write.txt
//directory文件的绝对路径F:\java\io\directory
//read文件的绝对路径F:\java\io\read.txt
//testFile文件的绝对路径C:\Users\Administrator\workspace\Demo\.\testFile.txt
//====================================================
//write文件的名称write.txt
//directory文件的名称directory
//read文件的名称read.txt
//testFile文件的名称testFile.txt
//====================================================
//write文件父文件夹的名称F:\java\io
//directory文件父文件夹的名称F:\java\io
//read文件父文件夹的名称F:\java\io
//testFile文件父文件夹的名称.
//====================================================
//write文件路径F:\java\io\write.txt
//directory文件路径F:\java\io\directory
//read文件路径F:\java\io\read.txt
//testFile文件路径.\testFile.txt
//====================================================
//write文件容量大小465g
//directory文件容量大小465g
//read文件容量大小465g
//testFile文件容量大小50g
//====================================================
//write文件剩余容量大小463g
//directory文件剩余容量大小463g
//read文件剩余容量大小463g
//testFile文件剩余容量大小22g
//====================================================
//write文件下文件null
//directory文件下文件[Ljava.lang.String;@15db9742
//read文件下文件null
//testFile文件下文件null

注意几个东西:
①lastModified方法返回的是时间戳,可以用dateFormat去格式化时间。
②getPath与getAbsolutePath的区别是,前者返回的是你输入的文件地址,后者返回的是这个文件本身的绝对路径地址。
③之所以前面3个文件获取到的总容量是一样的是因为,getTotalSpace方法计算的是整个F盘的大小。而在代码中新增的testFile文件是处于C盘。所以它的总容量和别的是不同的。同理,getFreeSpace方法也是这般。
④对于file.list方法。这个方法虽然说可以针对任意file对象,但是实际情况中,如果file指向的是真实文件而不是目录的时候返回的是null。只有当file对象是指向目录的时候才可以获取该目录下所有文件的名字。
⑤有的小伙伴会问legth方法directory里面明显有文件啊,为什么是0。我查看了length方法的源码,发现源码介绍中有这么一句“The return value is unspecified if this pathname denotes a directory”对于目录的结果返回是不确定的。如果有更好的解释,请联系我一起探讨。

4、深入一下String[] list(FilenameFilter filter) 方法
从这个方法可以看出,参数是一个FilenameFilter对象,经过博主查看之后,发现它是一个接口,且这个接口只有一个待实现方法,以下是它的源码:

@FunctionalInterface
public interface FilenameFilter {
    /**
     * Tests if a specified file should be included in a file list.
     *
     * @param   dir    the directory in which the file was found.
     * @param   name   the name of the file.
     * @return  <code>true</code> if and only if the name should be
     * included in the file list; <code>false</code> otherwise.
     */
    boolean accept(File dir, String name);
}

它这个accept方法可以处理某一个文件夹下的所有文件名称,拿到自己想要的一个或者一组文件。具体例子请参考下面这段代码:


package com.brickworkers.io;

import java.io.File;
import java.io.FilenameFilter;

public class Test {

    public static void main(String[] args) {

        File directory = new File("F:/java/io/directory");
        String[] directorys = directory.list(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                return name.indexOf("f")>-1;
            }
        });

        for (String string : directorys) {
            System.out.println(string);
        }
    }

}
//输出结果:
//file1.txt
//file2.txt
//file3.txt
//file4.txt
//

我是用匿名内部类来直接实现了这个接口,你也可以单独写一个处理方式实现这个接口,但是像我这样写是最简洁的。同时,在accept方法中,我要求把文件名称包含”f”的文件归入到我需要的集合中。这就是这个文件名称过滤接口的基本作用。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值