Java中的文件(File类)

这篇文章主要想介绍的就是File类,这个类既可以表示文件(文本、图片和视频),也可以表示文件夹(文件路径),因此使用起来也是非常方便。

1.文件(文本、图片和视频)
2.文件夹(文件路径)

主要是想写一下它的常用方法吧,还有比如遍历文件夹、查看文件夹里面某种类型的文件等操作

1.构造方法

File(File parent,String child)
File(String pathname)
File(String parent,String child)

构建文件对象的方法很多,直接传入文件所在的路径就可以得到文件对象,但是要注意,传入的路径参数应该是String类型的,所以传入 "C:\a.txt" 是不对的,因为 \是转义字符,要想表示这个字符,就必须使用 \\ 这样,当然不用 \ 这个斜杠也是可以的,将文件路径写成 C:/a.txt 也是可以的,这里就是使用的反斜杠 /,因此这两种方式都可以表示文件路径,但是使用反斜杠 / 这种方式并不推荐,具体完整的描述在下面说吧。

2.创建和删除方法

文件的创建

boolean createNewFile()

文件夹的创建

boolean mkdir()     单层路径
boolean mkdirs()    多层路径

当使用上面的构造方法创建了对于文件或文件夹的对象之后,其实只是相当于对传入路径的文件或文件夹有了一个引用,而不代表它们一定存在,如果不存在的话就需要创建它们了,而创建它们则可以使用上面列出的几个方法,对于文件的创建就应该使用 createNewFile() 方法,而文件夹则应该使用 mkdir()mkdirs() 了,关于文件夹创建的两个方法,区别主要就是在于要创建的文件夹是单层的还是多层的,单层就是使用 mkdir(),双层那就是使用 mkdirs() 了。

删除方法都是一样的

boolean delete() 

不过需要注意的是,删除文件夹的时候,它里面不能存在文件或者文件夹,也就是说在删除文件夹的时候,要首先删除掉它里面的文件和文件夹,当然如果它里面的文件夹同时也包含文件或文件夹的话,那就应该使用一个递归删除的方法,循环地去遍历,循环地删除。

3.判断方法

File类提供了一些常用的判断方法

boolean exists()        判断文件或者文件夹是否存在 
boolean isAbsolute()    判断当前的路径是否是绝对路径
boolean isDirectory()   判断当前的文件是否是文件夹
boolean isFile()        判断当前的文件是否是文件
boolean isHidden()      判断当前的文件是否是隐藏文件

其实看到名字就大致可以知道这些方法的用途了,确实是见名知意。

exist()是用来判断文件或者文件夹是否存在的,比如在读对文件进行读写操作之前,就需要先判断一下,这样也会比较严谨。

isAbsolute()方法则是用来判断调用该方法的路径是否为绝对路径,绝对路径一般就是从盘符出发的路径名,而与其相对应的便是相对路径,相对路径则是指一个文件相对于另一个文件所在的路径。

isDirectory()则是用来判断调用该方法的对象是否是一个目录(文件夹),它一般与isFile()这个方法结合使用,因为一般不是文件,那就是文件夹了,遍历一个目录的时候就需要进行这两者的区分了。

isFile()则是用来判断调用该方法的对象是否是一个文件,是文件便可以执行操作文件的方法,也是对于文件和文件夹的一个区分。

isHidden()则是用来判断这个文件是否是一个隐藏文件,测试这个方法可以先在文件的属性页面将文件设置为隐藏的,然后再调用这个方法查看结果。

4.获取方法

常用的获取方法有如下一些

File getAbsoluteFile()  
String getAbsolutePath() 
String getName()  
String getParent()  
File getParentFile() 
String getPath()  
long lastModified() 
long length()

上面这些方法很多都可以两两分成一组,因为很多都是一个返回字符串,一个返回对象

File getAbsoluteFile()  
String getAbsolutePath() 

这两个就是一个典型的例子,当我只是想输出一个文件或文件夹的绝对路径时,那我只需要调用getAbsolutePath()方法就可以了,因为打印信息的时候只需要字符串就可以满足功能了,而如果我还想使用这个路径做其它的功能,那就应该使用getAbsoluteFile()了,这次返回便是一个对象,使用这个对象是可以再创建其它新的对象的,就和File类的构造方法是一样的,就可以传入一个表示路径的字符串,当然也可以是一个表示路径的File对象了。

String getParent()  
File getParentFile()

这两个方法和上面的有同样的区别,那就是一个返回字符串,而另一个则是返回的对象,其实它们都是返回的父目录,只是表示方式不一样罢了。

String getName()                   
String getPath()

这两个方法就不是像之前的那样的联系了,第一个方法getName()是得到文件的名称,文件名以及后缀名,第二个方法getPath()是得到文件的路径,至于是绝对路径还是相对路径,就要看当初构造这个对象时使用的什么,当时传入的参数是什么,现在这个方法返回的就会是什么。

long lastModified()
long length()

第一个方法lastModified()返回的是这个文件最后修改的毫秒数,因为是毫秒数,那就和Date类的对象有点像了,表示的是距离某个时间点到现在的毫秒数,因此是可以用这个返回的值去构建一个Date对象的;第二个方法length()是返回当前文件的大小,单位是字节,如果需要得到比如兆(M)这样更加通用的格式,是需要自己进行转换的。

5.修改方法

boolean renameTo(File dest)

这个方法就是用来修改文件名称的,不过需要注意的是里面的参数不是String类型的,而是一个File类型的,因此要先使用想要修改的文件名构造一个File对象,然后再用想要改变名称的文件对象调用这个方法。

6.几个应用的小例子

6.1 打印某个目录下指定类型的文件(包含子目录)

public static void main(String[] args) {
    File file = new File("F:\\");
    printJavaFile(file);
}

public static void printJavaFile(File file) {
    if (file.isFile()) {
        if (file.getName().endsWith(".pdf")
                || file.getName().endsWith(".pdf")) {
            System.out.println(file.getPath());
        }
    } else if (file.isDirectory()) {
        File[] files = file.listFiles();
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                printJavaFile(files[i]);
            }
        }
    }
}

这个程序是打印出F盘符中所有pdf类型的文件,上面写的方法可以将文件目录传进去,其实方法中的文件类型也可以不用写死,比如pdf、java,也是可以设定一个String类型的参数进行传递的。

6.2 删除指定文件夹(包含文件和子文件夹)

public static void main(String[] args) {
    File f = new File("D:\\360Downloads");
    removeFile(f);
}

public static void removeFile(File file) {
    if (file.isFile()) {
        file.delete();
    } else if (file.isDirectory()) {
        File[] files = file.listFiles();
        // 消除空指针异常
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                File f = files[i];
                removeFile(f);
            }
        }
        file.delete();
    }
}

删除文件,直接调用delete()方法就好了,但是删除文件夹却需要多注意一点,如果文件夹里面还存在文件或子文件夹是删除不了的,因此如果想要删除文件夹就需要使用迭代方法了,是文件那就直接删除,但是如果是子文件夹,那就必须再去循环遍历这个子文件夹,里面是文件那就直接删除,如果还有子文件夹,那就再去遍历,当然当那个文件夹对象里面不存在东西的时候,也就可以调用delete()方法了。

6.3 计算一个文件夹的大小

我们知道对于文件大小是有一个length()方法的,返回的是这个文件的字节数,但是文件夹对象是没有这样的方法的,那最直接的方法就是把文件夹里面所有文件的大小加起来,那就是整个文件夹的大小了,所以这里我就先遍历一次文件夹,将文件夹里面的文件对象全部装到一个集合之中,然后再循环遍历这个集合,依次计算文件的大小,以此来计算文件夹的大小,这样计算就分为两步了,第一步是将文件装入集合当中,第二步就是计算集合中文件的大小,当然也可以直接在遍历集合的时候将文件的大小加起来,但感觉还是没有这样分为两步之后来的直观和好理解。

public static void main(String[] args) {
    List<File> array = new ArrayList<File>();
    File file = new File("D:\\Blog");
    calFileSize(file, array);
    long size = 0;
    for (int i = 0; i < array.size(); i++) {
        File f = array.get(i);
        size += f.length();
    }
    System.out.println(size);
    String big = MySizeTool.formatFileSize(size, true);
    System.out.println(big);
}

public static void calFileSize(File file, List<File> array) {
    if (file.isFile()) {
        array.add(file);
    } else if (file.isDirectory()) {
        File[] files = file.listFiles();
        if (files != null) {
            for (int i = 0; i < files.length; i++) {
                File f = files[i];
                calFileSize(f, array);
            }
        }
    }
}

这里面最后得到所有文件的字节数之后,有一个将字节数转换单位的工具类,这里也直接放在下面了。

public class MySizeTool {
    /**
     * 通过字节数得到当前的格式化字符串数据
     * @param size 字节数大小
     * @param flag 是否保留2位小数. true表示保留,false表示不保留
     * @return 格式化好的字符串数据,例如: 36MB 或者 36.30MB
     */
    public static String formatFileSize(long size, boolean flag) {
        // 定义需要返回的字符串
        String result = null;
        // 定义字符串
        String grade = null;
        // 定义整数部分和小数部分
        long zhengShu = 0;
        double xiaoShu = 0;
        // 将size赋值
        long mSize = size;
        // 查看使用什么级别的数据
        int count = -1;
        while (mSize > 0) {
            // 计算需要多少个1024
            mSize /= 1024;
            count++;
        }
        // 如果需要0-B 1-KB 2-MB 3-GB 4-TB 5-PB

        switch (count) {

        case 0:
            result = size + "B";
            break;
        case 1:
            zhengShu = size >> 10;
            xiaoShu = 1.0 * size / 1024 - zhengShu;
            grade = "KB";
            break;
        case 2:
            zhengShu = size >> 20;
            xiaoShu = 1.0 * size / 1024 / 1024 - zhengShu;
            grade = "MB";
            break;
        case 3:
            zhengShu = size >> 30;
            xiaoShu = 1.0 * size / 1024 / 1024 / 1024 - zhengShu;
            grade = "GB";
            break;
        case 4:
            zhengShu = size >> 40;
            xiaoShu = 1.0 * size / 1024 / 1024 / 1024 / 1024 - zhengShu;
            grade = "TB";
            break;
        case 5:
            zhengShu = size >> 50;
            xiaoShu = 1.0 * size / 1024 / 1024 / 1024 / 1024 / 1024 - zhengShu;
            grade = "PB";
            break;
        }
        // 判断
        if (count != 0) {
            // 得到结果
            result = calculate(flag, zhengShu, xiaoShu, grade);
        }
        // 返回数据
        return result;
    }

    // 用于计算的操作
    private static String calculate(boolean flag, long zhengShu,
            double xiaoShu, String grade) {
        String result;
        String xs;
        xs = xiaoShu + "";
        // 去掉前面两个字符 0
        // 是否可以保留数据
        if (flag == true) {
            if (xs.length() < 2) {
                xs = ".00";
            } else {
                xs = xs.substring(1, 4);
            }
            result = zhengShu + xs + grade;
        } else {
            result = zhengShu + grade;
        }
        return result;
    }
}

6.4 确定一个文件目录中文件类型以及各种类型文件的个数

解决这个问题主要是分两步,首先是要确定这个路径下有哪些类型的文件,当然主要是看文件的后缀名了,第二步再是去确定各个类型文件的数量,就是在遍历的过程中碰到某一种类型的文件,先将这种类型文件的数量取出来,然后在加1之后,再保存回去,这样就相当于增加了这一类型文件的数量。

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
import java.util.Set;

public class Test3 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入一个文件夹路径:");
        String path = sc.nextLine();
        File file = new File(path);

        Map<String, Integer> map = new HashMap<String, Integer>();
        getKey(file, map);
        getNum(file, map);
        Set<Entry<String, Integer>> entrys = map.entrySet();
        for (Entry<String, Integer> entry : entrys) {
            String key = entry.getKey();
            int num = entry.getValue();
            if (key == null) {
                System.out.println("没有后缀名的文件有" + num + "个");
            } else {
                System.out.println(key + "类型的文件有" + num + "个");
            }
        }
    }

    public static void getKey(File file, Map<String, Integer> map) {
        if (file.isFile()) {
            if (!(file.getName().contains("."))) {
                map.put(null, 0);
            } else if (file.getName().contains(".")) {
                String[] names = file.getName().split("\\.");
                String key = names[names.length - 1];
                map.put(key, 0);
            }
        } else if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (int i = 0; i < files.length; i++) {
                    File f = files[i];
                    if (f.isFile()) {
                        if (!(f.getName().contains("."))) {
                            map.put(null, 0);
                        } else if (f.getName().contains(".")) {
                            String[] names = f.getName().split("\\.");
                            String key = names[names.length - 1];
                            map.put(key, 0);
                        }
                    } else if (f.isDirectory()) {
                        getKey(f, map);
                    }
                }
            }
        }
    }

    public static void getNum(File file, Map<String, Integer> map) {
        if (file.isFile()) {
            if (!(file.getName().contains("."))) {
                int num = map.get(null);
                map.put(null, num + 1);
            } else if (file.getName().contains(".")) {
                String[] names = file.getName().split("\\.");
                String key = names[names.length - 1];
                int num = map.get(key);
                map.put(key, num + 1);
            }
        } else if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files != null) {
                for (int i = 0; i < files.length; i++) {
                    File f = files[i];
                    if (f.isFile()) {
                        if (!(f.getName().contains("."))) {
                            int num = map.get(null);
                            map.put(null, num + 1);
                        }
                        if (f.getName().contains(".")) {
                            String[] names = f.getName().split("\\.");
                            String key = names[names.length - 1];
                            int num = map.get(key);
                            map.put(key, num + 1);
                        }
                    } else if (f.isDirectory()) {
                        getNum(f, map);
                    }
                }
            }
        }
    }
}

7.文件分隔符

这里主要是想说一下文件分隔符,之前在构造函数中,说传入的字符串路径 C:\\a.txtC:/a.txt 都是可以的,但是不推荐使用 C:/a.txt ,这是为什么呢?先说明一下反斜杠 / ,为什么它可以用作文件分隔符呢,是因为大部分Windows文件处理的函数调用都会将反斜杠 / 解释成文件分隔符,但是Windows系统函数的行为可能因为更新而发生变化,所以对于强调可移植性的程序来说,应该使用程序所运行平台的文件分隔符。

获取程序所运行平台的文件分隔符:

System.out.println(java.io.File.separator);

那就应该运行一下上面这条语句。没错会输出一个 \,只不过 \ 在Java中是转义字符,为了表示它,那就要使用 \\了。

以上内容,我也是在《Java核心技术 卷II》中看到的,看来,读书还是可以得到很多细节的。

8.总结

看来提供的几个简简单单的方法,结合起来之后,就还可以写出蛮不错的程序,继续多敲多阅读吧!

坚持原创技术分享,您的支持将鼓励我继续创作!