zoukankan      html  css  js  c++  java
  • java IO(一):File类

    1.File类简介

    File类位于java.io包中。它面向文件层次级别操作、查看文件,而字节流、字符流操作数据时显然比之更底层。

    学习File类包括以下几个重点:文件路径、文件分隔符、创建文件(目录)、删除文件(目录)、查看文件内容(输出目录内文件)、判断文件(是文件/目录?存在否?可读写执行?)、获取文件信息(文件名、路径名、大小等),最后还有如何筛选所需文件

    2.创建、删除文件/目录

    File类有四个构造方法:File(String pathname)、File(String parent,String child)、File(File parent,String child)、File(URI uri),暂不考虑最后一个。

    File file1 = new File("D:\myjava\a.txt");      //File(String pathname)
    File file2 = new File("D:\myjava","a\b.txt");  //File(String parent,String child)
    File file3 = new File(file2,"abc");            //File(File parent,String child)
    

    new一个File对象后,表示创建了一个File实例,不代表在文件系统中创建了实际的文件。要创建实际的文件、目录,应该使用File类中提供的方法:

    • boolean createNewFile() throws IOException:创建一个新的空文件,仅当文件不存在时才创建并返回true。
    • static createTempFile():创建临时文件。
    • boolean mkdir():创建空目录,仅当父路径存在且待创建目录不存在时才创建并返回true。注:不会递归创建父目录。
    • boolean mkdirs():和mkdir()不同的是,mkdirs()会递归创建所有所需要的父路径。

    例如,在d:myjava(已存在)中创建d:myjavaa.txt,d:myjavaaabcc.txt,以下提供了一种方法。

    File file0 = new File("xyz.txt");   //相对路径,相对于system属性中的user.dir路径
    File file1 = new File("D:\myjava\a.txt");
    File file2 = new File("D:\myjava","a\abc");
    File file3 = new File(file2,"c.txt");
    
    try {
        System.out.println(file1.createNewFile());   //try ... catch createNewFile()
        System.out.println(file2.mkdirs());
        System.out.println(file3.createNewFile());
    } catch (IOException e) {
        e.printStackTrace();
      }
    

    注意上面的双反斜线\,因为Windows系统的文件分隔符为,而这是转义符号,因此需要对自身进行转义。Unix操作系统中的文件分隔符号为/,但Windows也同样能够正确使用/作为分隔符。

    执行代码,由于第一次创建文件,所以都返回true,但第二次执行都将返回false,因为待创建文件都已存在。如下:

    λ java TestCreate
    true
    true
    true
    
    
    λ java TestCreate
    false
    false
    false
    

    File类只提供了一个delete()方法用来删除文件和目录,且删除目录时只能删除空目录。注:此为永久删除,不进入回收站。

    System.out.println(file1.delete()); //true
    System.out.println(file2.delete()); //false
    File file4 = new File("d:/myjava/a/abc/c.txt");
    System.out.println(file4.delete()); //true
    

    文件名和路径相关问题

    每一个File对象都有父路径、文件名,两者结合就是文件的绝对路径。此外,路径还分为相对路径(抽象路径)、绝对路径。

    以unix的路径命名方式为例,绝对路径/etc/ssh/ssh_config中/etc/ssh为dirname,即父路径,ssh_config为basename。Windows中也差不多,如绝对路径c:windowssystem32driversetchosts中的dirname为c:windowssystem32driversetc,basename部分为hosts。

    以下是File类提供的与文件名、父路径、路径相关的方法。

    • getName():获取文件名。获取的内容是file对象中给定的抽象路径名,即路径的basename部分。
    • getAbsoultePath():获取绝对路径名,即dirname/basename。
    • getParent():获取父路径,即dirname。
    • getPath():获取文件路径的字符串,其实调用的是toString()。可能返回相对路径、也可能绝对路径。见下文解释。
    • File getAbsoulteFile():获取绝对路径的文件对象,注意返回File。
    • File getParentFile():获取父路径的文件对象,注意返回File。

    在new File时,可以给定相对路径(相对于user.dir),也可以给定绝对路径。例如,下面4个new File中,除了第一个是相对路径,其余三个都是绝对路径。

    File file0 = new File("xyz.txt");     //相对路径,相对于system属性中的user.dir路径
    File file1 = new File("D:\myjava\a.txt");
    File file2 = new File("D:\myjava","a\abc");
    File file3 = new File(file2,"c.txt");
    

    当给定是相对路径时,则getParent()和getParentFile()无法正确获取到父路径,返回NULL,且getPath()返回的将是相对路径的文件名,即new File(PATH)给定什么PATH,就返回什么PATH。但无论如何,getAbsoultePath()总是能获取到绝对路径。

    File file0 = new File("1.txt");
    File file1 = new File("D:/myjava/a.txt");
    File file2 = new File("D:/myjava","a/abc");
    File file3 = new File(file2,"c.txt");
    System.out.println("----------file0-----------------");
    System.out.println(file0.getAbsoluteFile());   //D:myjavaio1.txt
    System.out.println(file0.getAbsolutePath());   //D:myjavaio1.txt
    System.out.println(file0.getName());           //1.txt
    System.out.println(file0.getParent());         //null
    System.out.println(file0.getParentFile());     //null
    System.out.println(file0.getPath());           //1.txt
    System.out.println("----------file1-----------------");
    System.out.println(file1.getAbsoluteFile());   //D:myjavaa.txt
    System.out.println(file1.getAbsolutePath());   //D:myjavaa.txt
    System.out.println(file1.getName());           //a.txt
    System.out.println(file1.getParent());         //D:myjava
    System.out.println(file1.getParentFile());     //D:myjava
    System.out.println(file1.getPath());           //D:myjavaa.txt
    System.out.println("----------file2-----------------");
    System.out.println(file2.getAbsoluteFile());   //D:myjavaaabc
    System.out.println(file2.getAbsolutePath());   //D:myjavaaabc
    System.out.println(file2.getName());           //abc
    System.out.println(file2.getParent());         //D:myjavaa
    System.out.println(file2.getParentFile());     //D:myjavaa
    System.out.println(file2.getPath());           //D:myjavaaabc
    System.out.println("----------file3-----------------");
    System.out.println(file3.getAbsoluteFile());   //D:myjavaaabcc.txt
    System.out.println(file3.getAbsolutePath());   //D:myjavaaabcc.txt
    System.out.println(file3.getName());           //c.txt
    System.out.println(file3.getParent());         //D:myjavaaabc
    System.out.println(file3.getParentFile());     //D:myjavaaabc
    System.out.println(file3.getPath());           //D:myjavaaabcc.txt
    

    3. 文件判断和文件属性相关

    new File对象时,无论这个对象是文件还是目录,new的方式是一样的,也就是说,从new File无法识别出这个对象是文件还是目录,也无法确认这个对象对应的文件是否存在。此外,这个文件是否可读、可写、可执行等也都可以进行判断。其实这些都算是文件的属性信息,除了这些信息外,文件名、文件大小、最近一次修改时间等也都是文件属性。

    • exists():File对象在文件系统中是否存在。
    • isFile():File对象在文件系统中是否存在且是否为普通文件。
    • isDirectory():File对象在文件系统中是否存在且是否为目录。
    • canRead():File对象是否可读。
    • canWrite():File对象是否可写。
    • canExecute():File对象是否可执行。

    还有两个获取常见属性的方法:

    • length():文件大小,单位字节。可用来判断是否为空文件、空目录。
    • lastModified():最近一次修改时间,即mtime。

    还可以设置读、写、执行、最近修改时间等属性。

    • setLastModified(long time):time用从1970-01-01开始的毫秒数表示。
    • setExecutable(true/false):对所有用户是否可执行,参数为true或false
    • setExecutable(true/false,true/false):第二个参数表示owneronly,为true时表示只有所有者可执行,否则表示所有用户可执行。
    • setWritable(true/false):和setExecute()一样,也支持owneronly参数。
    • setReadable(true/false):和setExecute()一样,也支持owneronly参数。
    • setReadOnly():设置只读,设置成功返回true。

    4. 列出目录内文件

    File类中没有提供查看文件内容的方法,仅只提供了查看目录内容的方法,也就是列出目录内的文件列表。这些方法都只能列出当前目录内容,不会递归到子目录中去遍历。

    • String[] list():返回一个字符串数组,元素为此目录中文件的basename。
    • String[] list(FilenameFilter filter):返回一个字符串数组,元素为满足过滤条件的basename。
    • File[] listFiles():返回一个抽象路径名数组,元素为此目录中文件的basename。
    • File[] listFiles(FileFilter filter):返回抽象路径名数组,元素为满足过滤条件的basename。
    • File[] listFiles(FilenameFilter filter):返回抽象路径名数组,元素为满足过滤条件的baesname。

    因为文件列表返回的是多个值,甚至是多个File对象,因此这些方法返回值都是数组形式。之所以是数组而不是集合,是因为数组中的元素数量是不可更改的,而列出目录中文件列表本就是列出当前时刻目录内文件的动作,如果有增、删元素的操作,岂非列出前是一个列表,实际列出的又是另一个列表?

    首先看不带过滤器的list()和listFiles(),关于文件筛选的方法见后文。假设D:a目录内的结构如下:

    d:a
    |--a.sql
    |--back.log
    |--b
    |  |--e
    |  |  |--1.txt
    |  |  |--2.txt
    |  |  `--3.txt
    |  `--f
    |     |--4.txt
    |     |--5.txt
    |     `--6.txt
    |--c
    |  |--e
    |  |  |--ace1.txt
    |  |  |--ace2.txt
    |  |  `--ace3.txt
    |  `--f
    |     |--4.txt
    |     |--5.txt
    |     `--6.txt
    `--d
       |--a.java
       |--abc (1).txt
       |--abc (2).txt
       |--abc (3).txt
       |--b.java
       `--c.java
    

    列出D:a内的文件列表。

    File file1 = new File("d:/a");
    String[] list = file1.list();
    for (String f : list) {
        System.out.println(f);
    }
    

    得到的结果为

    a.sql
    b
    back.log
    c
    d
    

    实际的过程是将目录内的文件名存放到了字符串数组中,再遍历数组。而且,得到的结果仅仅只是basename部分的文件名,不是绝对路径。实际上,因为存储在String[]中,完全没办法得到其绝对路径。因此,更好的方式是使用listFiles()方法,因为它返回的是File数组,其内每一个元素都是File对象,可以使用getAbsolutePath()来获取各元素的绝对路径。

    File file1 = new File("d:/a");
    File[] filelist = file1.listFiles();
    for (File file : filelist) {
        System.out.println(file.getAbsolutePath());
    }
    

    得到的结果为:

    d:aa.sql
    d:a
    d:aack.log
    d:ac
    d:ad
    

    关于列出目录,有如下几个示例,见:java显示目录文件列表和删除目录
    示例1:列出整个目录中的文件(递归)
    示例2:列出整个目录中的文件(队列)
    示例3:树形结构显示整个目录中的文件(递归)
    示例4:删除整个目录

    5.筛选文件

    File类的listFiles()支持文件筛选功能。例如File[] listFiles(FileFilter filter),其中FileFilter为过滤器接口,需要实现该接口来筛选文件。

    常用的筛选方法是根据文件名,其实也支持其他筛选条件,如是否可读、大小是否大于5M等。

    import java.io.*;
    
    public class Filter1 {
        public static void main(String[] args) {
            File dir = new File("d:/myjava");
            getJavaFiles(dir);
        }
    
        public static void getJavaFiles(File dir) {
            File[] files = dir.listFiles(new NameFilter());
            for (File file:files) {
                if(file.isDirectory()) {
                    getJavaFiles(file);
                } else {
                    System.out.println(file.getAbsolutePath());
                }
            }
        }
    }
    
    
    //实现FileFilter接口
    class NameFilter implements FileFilter {
        public boolean accept(File pathname) {
            if(pathname.isDirectory()) {    //为了支持递归筛选,判断目录
                return true;
            } else {
                String name = pathname.getName();
                return name.endsWith(".class")?true:false;
    
                //return pathname.canRead()?true:false;        //根据是否可读筛选
                //return pathname.length()>5242880?true:false;  //根据大小筛选great than 5MB?(5*1024*1024)
            }
        }
    }
    

    注:若您觉得这篇文章还不错请点击右下角推荐,您的支持能激发作者更大的写作热情,非常感谢!

  • 相关阅读:
    cmake vs qmake
    Flutter安装过程中遇到的问题
    外观模式(c++实现)
    原型模式(c++实现)
    我敢说 80% 的程序员都掉进了「老鼠赛跑」的陷阱
    装饰模式(c++实现)
    Kubernetes 部署 Nebula 图数据库集群
    应用 AddressSanitizer 发现程序内存错误
    前端 Docker 镜像体积优化
    图数据库设计实践 | 存储服务的负载均衡和数据迁移
  • 原文地址:https://www.cnblogs.com/f-ck-need-u/p/8143690.html
Copyright © 2011-2022 走看看