Java 基础之 File

版权声明:本文为博主原创文章,转载请注明出处: https://blog.csdn.net/qq_38182125/article/details/90610585

一、概述

File 类在日常的开发中应当是不少见的,只要是涉及到文件读写的,往往都需要借助 File 类。本篇文章为笔者的读书笔记,将对 File 类的使用做一个简单的介绍,内容如下所示:

  • File 是什么
  • File 的构造方法
  • File 的常用方法
  • File 的简单例子

接下来我们就根据上面的列举出来的内容概要对 File 类进行较为详细的介绍。


二、什么是File

File 类是 java.io 包中唯一代表磁盘文件本身的对象。File 类定义了一些与平台无关的方法来操作文件来操作文件,可以通过调用 File 类的方法,实现创建、删除、重命名文件等操作。File 类的对象主要用来获取文件本身的一些信息,如文件所在的目录、文件的长度、文件的读写权限等。此外 File 类还有以下几点注意事项:

  • File 对象除了能表示文件本身外,还能表示文件目录;
  • File 对象并非就是文件本身,它实际上代表的是和实际文件的一种联系,是一个抽象的表现形式,这种联系通过虚拟机来维持;
  • 从第二点可知,File 对象所指代的文件并不一定是真实存在的,它有可能为空。

在大致了解了 File 类的作用之后,接下来我们就从构造方法入手,来了解 File 类是如何使用的。


三、File 类的构造方法

File 类有以下 4 个构造方法,构造方法及其参数的含义如下表所示:

方法 说明
File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例。
File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的 File实例。
File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的 File实例。
File(URI uri) 通过将给定的 file: URI转换为抽象路径名来创建新的 File实例。

接下来我们就通过几个例子来了解下它们各自的使用。

File(String pathname)

我们假定文件所在的位置为 C:\Users\Marck\Desktop\demo.jpg。这是笔者电脑桌面上的一张图片,我们需要创建一个 File 实例来表示这张图片文件,代码如下所示:

public class FileDemo {
    public static void main(String[] args) {
        String path = "C:\\Users\\Marck\\Desktop\\demo.jpg";
        // 构建File对象
        File file = new File(path);
    }
}

这里需要注意的是字符 '\' 需要使用转义字符 '\\' 来表示。

接着我们思考一个问题:上述的文件路径 C:\Users\Marck\Desktop\demo.jpg 是在 Windows 系统下的路径表示形式,但在其他操作系统上路径分隔符就未必是 '\' 了。那么是否有什么方法可以统一表示不同平台下的路径分隔符呢?

答案是采用符号 '/' 或者调用 File.separator。上述图片的文件路径分隔符采用 '/' 来表示之后即为 C:/Users/Marck/Desktop/demo.jpg,这种形式在任何平台下都是通用的;而调用 File.separator 的方式也可以达到同样的效果,上述路径在这种形式下表示为:

"C:" + File.separator + "Users" + File.separator + "Marck" + File.separator + "Desktop" + File.separator + "2.JPG";

它同样也可以达到跨平台通用的效果,但一般而言我们更愿意使用 '/' 的表示形式,因为调用 File.separator 的方式往往会比较麻烦。

File(String parent, String child)

依然以上面的图片文件路径 C:\Users\Marck\Desktop\demo.jpg 为例,将 C:\Users\Marck\Desktop 作为其父路径,代码如下所示:

public class FileDemo {
    public static void main(String[] args) {
        String parentPath = "C:/Users/Marck/Desktop";
        File file = new File(parentPath, "demo.jpg");
    }
}

通过该构造方法创建的 File 实例与第一种方法达到的效果是一致的。

File(File parent, String child)

这个构造方法其实和第二种构造方法的使用是非常相似的,只不过第一个参数 parent 的类型为 File,依旧以上面图片文件的路径为例创建该图片文件的 File 对象:

public class FileDemo {
    public static void main(String[] args) {
        File file = new File(new File("C:/Users/Marck/Desktop"), "demo.jpg");
    }
}

通过该构造方法创建的 File 实例与第二种方法达到的效果是一致的。

File(URI uri)

这个构造方法应该是最不常使用的了,它需要借助统一资源标识符 URI 类来辅助构造 File 实例,代码如下所示:

public class FileDemo01 {
    public static void main(String[] args) throws URISyntaxException {
        URI uri = new URI("file:/C:/Users/Marck/Desktop/demo.jpg");
        File file = new File("C:/Users/Marck/Desktop/demo.jpg");
    }
}

由于 URI 的知识与本主题无关,所以这里只做简单介绍,上述代码创建出来的 File 实例与前面三种构造方法创建出来的实例效果是一致的。


四、File的常用方法

File 的方法非常的多,下面只列举出日常使用频率较高的几个方法,其它方法可以在 Java 官方文档中自行查看,常用方法如下表所示:

方法 说明
getName() 返回 File对象表示的文件或目录的名称。
getPath() 返回 File对象的路径名字符串。
getAbsoultPath() 返回 File对象的绝对路径名字符串。
getParent() 返回 File对象的父路径名字符串,如果File对象没有父目录,则返回null。
exists() 测试 File对象表示的文件或目录是否存在。
isFile() 测试 File对象表示的文件是否为普通文件。
isDirectory() 测试 File对象表示的文件是否为目录。

上表中的这些方法都比较简单,这里就不一一举例子了。唯一需要注意的是 getPath 方法,如果构建的 File 实例路径为相对路径,那么 getPath 返回的也是相对路径名,如果构建的 File 实例路径为绝对路径,那么 getPath 返回的就是绝对路径名,下列代码对其进行了验证:

public class FileDemo {
    public static void main(String[] args) {
        // 传入参数为相对路径
        File file = new File("demo.jpg");
        System.out.println(file.getPath());
        // 传入参数为绝对路径
        file = new File("C:/Users/Marck/Desktop/demp.jpg");
        System.out.println(file.getPath());
    }
}

输出结果如下:

demo.jpg
C:\Users\Marck\Desktop\demp.jpg

与上面我们所说的情况一致。接下来看到几个文件的列举方法,它们用于列举出目录中的文件:

方法 说明
list() 返回一个字符串数组,命名由 File对象表示的目录中的文件和目录。
list(FilenameFilter filter) 返回一个字符串数组,命名由 File 对象表示的目录中满足指定过滤器的文件和目录。
listFiles() 返回一个 File 数组,表示由 File对象表示的目录中的文件。
listFiles(FilenameFilter filter) 返回一个 File 数组,命名由 File 对象表示的目录中满足指定过滤器的文件和目录。
listRoots() File 类的静态方法,列出可用的文件系统根。

接下来通过几个例子来说明上述方法的使用。

list()

假设我们现在要列出桌面上的文件名,代码如下所示:

public class FileDemo {
    public static void main(String[] args) {
        File file = new File("C:/Users/Marck/Desktop");
        String[] files = file.list();
        for (String s : files){
            System.out.println(s);
        }
    }
}

运行结果如下:

360安全浏览器.lnk
Atom.lnk
Charles.lnk
Cisco Packet Tracer.lnk
CodeBlocks.lnk

可以看到成功地打印出了当前目录下的所有文件和目录,如果 File 实例代表的是一个文件对象,list 方法会返回 null。

listFiles()

listFiles 方法和 list 方法是很相似的,只不过 list 返回的是文件名的字符串数组,而 listFiles 返回的则是 File 数组,代码如下所示:

public class FileDemo {
    public static void main(String[] args) {
        File file = new File("C:/Users/Marck/Desktop");
        File[] files = file.listFiles();
        for (File f : files){
            System.out.println(f.getPath());
        }
    }

运行结果如下所示:

C:\Users\Marck\Desktop\360安全浏览器.lnk
C:\Users\Marck\Desktop\Atom.lnk
C:\Users\Marck\Desktop\Charles.lnk
C:\Users\Marck\Desktop\Cisco Packet Tracer.lnk
C:\Users\Marck\Desktop\CodeBlocks.lnk

如果 File 对象代表的是一个文件而不是一个目录的话,同样会返回 null。

listRoots()

listRoots 方法返回的是文件系统的根目录,需要注意的是它是 File 类的静态方法,返回的是 File 数组。代码如下所示:

public class FileDemo {
    public static void main(String[] args) {
        File[] files = File.listRoots();
        for (File f : files){
            System.out.println(f.getPath());
        }
    }
}

运行结果如下:

C:\
D:\
E:\

笔者使用的是 Windows 系统,所以返回的是系统中三个盘的盘符。而如果是在 Linux 系统下运行此段代码,运行结果如下所示:

/

这和我们的认知也是一致的。接下来我们来了解如何使用 File 来创建/删除文件/目录。

方法 说明
mkdir() 创建由此 File 对象命名的目录。如果 File 对象路径中包含不存在的目录,创建失败。
mkdirs() 创建由此 File 对象命名的目录,包括任何必需但不存在的父目录。
createNewFile() 当且仅当具有该名称的文件尚不存在时,创建一个由此 File 对象命名的新的空文件。
delete() 删除此 File 对象表示的文件或目录。

接下来通过例子来介绍这些方法的使用。

mkdir & mkdirs

这两个方法都是用于创建文件目录的,唯一的区别是如果 File 对象路径中包含不存在的目录,mkdir 会创建失败,而 mkdirs 方法则会创建出所有不存在的目录。举一个例子:在 C:/Users/Marck /Desktop 这个路径下,我们要创建一个 Temp 目录,Temp 目录还要再创建一个 child 子目录,那么它可表示为:C:/Users/Marck/Desktop/Temp/child。注意此时 Temp 目录和 child 目录均是不存在的。

我们试着用 mkdir 方法来创建 child 目录,代码如下所示:

public class FileDemo {
    public static void main(String[] args) {
        File file = new File("C:/Users/Marck/Desktop/Temp/child");
        boolean flag = file.mkdir();
        System.out.println(flag);
    }
}

我们用一个 boolean 变量 flag 来接收 mkdir 方法的返回值,打印出结果值来判断是否创建成功,运行代码,输出结果如下:

false

表示创建 child 目录失败,其实原因也很简单,child 的父目录 Temp 是还未存在的,所以 mkdir 方法无法创建 child 目录。所以 mkdir 方法创建成功必须保证该目录下的父目录都是存在的,上述的情况适宜使用 mkdirs 方法,它的好处是只要该路径下的目录不存在那么就会创建出来,代码如下所示:

public class FileDemo {
    public static void main(String[] args) {
        File file = new File("C:/Users/Marck/Desktop/Temp/child");
        boolean flag = file.mkdirs();
        System.out.println(flag);
    }
}

运行结果如下所示:

true

我们去往桌面上查看时,也可以发现确实创建了 Temp 目录和它的子目录 child。除此之外我们还得意识到一点是无论是 mkdir 还是 mkdirs,当子目录已经存在时,会直接返回 false。例如上述 mkdirs 的示例代码再运行一次,就会发现打印出来的结果是 flase 了,因为此时 child 目录已经存在了。

createNewFile()

createNewFile 方法用于创建新文件(注意不是目录),例如我们要在桌面上创建一个 1.txt 的文本文件,代码如下所示:

public class FileDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("C:/Users/Marck/Desktop/1.txt");
        boolean flag = file.createNewFile();
        System.out.println(flag);
    }
}

运行代码,结果如下所示:

true

去往桌面上查看时我们也可以发现确实新建了一个空文本文件 1.txt。需要注意的是 createNewFile 方法会抛出 IOException 异常,并且当所在路径的 1.txt 文件存在的时候,同样也会返回 false,表示文件创建失败。

delete()

delete 方法从名字上也能知道是用于删除文件或目录的方法,它在文件存在时删除成功并返回 true,否则的话就会返回 false,例子如下所示:

public class FileDemo01 {
    public static void main(String[] args){
        File file = new File("C:/Users/Marck/Desktop/1.txt");
        boolean flag = file.delete();
        System.out.println(flag);
    }
}

运行结果如下:

true

表示成功地删除了文件 1.txt。如果我们再运行一次上面的代码,会发现返回的是 false,因为 1.txt 文件此时已经不存在了。


五、File的简单例子

这里我们通过 2 个小例子展示 File 的简单使用。

1. 列举出当前目录的所有文件名

通过前面的示例我们知道 list/listFiles 方法只能列举出当前目录下的文件,如果想要列举出目录下的所有文件,例如子目录下的文件,就可以使用到递归的方式来完成,代码如下所示:

public class FileDemo {
    public static void main(String[] args){
        File file = new File("C:/Users/Marck/Desktop");
        printFilename(file);
    }

    public static void printFilename(File file){
    	// 递归终止条件:file 为空或者不存在
        if (file == null || !file.exists()){
            return;
        }
        // 打印文件名
        System.out.println(file.getName());
        // 如果文件为目录,回调自身,继续打印
        if (file.isDirectory()){
            for (File f : file.listFiles()){
                printFilename(f);
            }
        }
    }
}

2. 计算文件的大小

这个问题我们需要借助 File 的 length() 方法,它用于计算出文件的大小,单位为字节(byte)。值得注意的是如果调用该方法的 File 对象代表的是一个目录,那么它的返回值就为 0。所以我们同样需要遍历该目录下的所有文件,统计出所有文件的大小相加返回,代码如下所示:

public class FileDemo {

    public static int totalLength = 0;

    public static void main(String[] args){
        File file = new File("C:/Users/Marck/Desktop/简历管理");
        countLength(file);
        System.out.println(totalLength);
    }

    public static void countLength(File file){
        if (file == null || !file.exists()){
            return;
        }
        if (file.isFile()){
            totalLength += file.length();
        } else {
            for (File f : file.listFiles()){
                countLength(f);
            }
        }
    }


}

这里采用了一个静态变量辅助进行计算,可以看到 countLength 的思路实际上和第一题的思路并无二致,而更好的方法则由各位具体去发现了。例如可以将递归改为循环的方式从而避免 StackOverflow 的情况发生。


希望这篇文章对您有所帮助~

猜你喜欢

转载自blog.csdn.net/qq_38182125/article/details/90610585