深入理解JAVA IO系列一:File详解

简介javaIO

从1.4版本开始JAVA引入了NIO,用来提升I/O性能。I/O操作类在包java.io下,大概有将近80个类,这些类可以分为如下四组:

  基于字节操作的I/O接口:InputStream和OutputStream

  基于字符操作的I/O接口:Reader和Writer

  基于磁盘操作的I/O接口:File

  基于网络操作的I/O接口:Socket

从字面意思理解,前两组主要是传输数据的格式,后两组是传输数据的方式。虽然Socket类并不在java.io包下,但是我们仍然将其归类在一起来讨论。因为我个人认为I/O的核心问题要么是数据格式影响I/O操作,要么是传输方式影响I/O操作。最终的问题也就是将什么样的数据写到什么地方的问题
File类

简介File

本篇文章主要介绍File类的一些常用方法,首先来看下一些重要的概念:

1、一个File类的对象,表示磁盘上的文件或目录。

2、File提供了与平台无关的方法来对磁盘上的文件或目录进行操作。

3、File类直接处理文件和文件系统。

4、File类没有指定信息怎样从文件读取或向文件存储。

File对象的构造

 @Test
    /**
     * 构造File路径的三种方法
     */
    public void test1() {
    File file1 = new File("E:\\workspace\\a.txt");
    File file2 = new File("E:/workspace/a.txt");
    System.out.println(File.separator);
    System.out.println(System.getProperty("file.separator"));
    File file3 = new File("E:"+File.separator+"workspace"+File.separator+"a.txt");
    System.out.println(file1.getName()+"\n"+file2.getName()+"\n"+file3.getName());

    }

File.separator和System.getProperty(“file.separator”)
两者都是获取路径分隔符,windows系统的路径分隔符为\,linux系统的路径分隔符为/,不过/在windows中也通用

三种对象的构造方法

File(String directoryPath)
File(String directoryPath, String filename)
File(File dirObj, String filename)

这里,directoryPath是文件的路径名,filename 是文件名,dirObj 一个指定目录的File 对象。

@Test
    /**
     * File对象的三种构造函数
     */
    public void test2() {
    File dir = new File("E:/workspace");
    File file1 = new File("E:/workspace","a.txt");
    File file2 = new File(dir,"a.txt");
    File file3 = new File("E:/workspace/a.txt");
    System.out.println(file1.getName()+"\n"+file2.getName()+"\n"+file3.getName());

    }

File对象的一些方法

@Test
    /**
     * File对象的属性类方法
     */
    public void test3() {
    File f1 = new File("E:/workspace","a.txt");
     p("File Name: " + f1.getName());
     p("Path: " + f1.getPath());
     p("Abs Path: " + f1.getAbsolutePath());
     p("Parent: " + f1.getParent());
     p(f1.exists() ? "exists" : "does not exist");
     p(f1.canWrite() ? "is writeable" : "is not writeable");
     p(f1.canRead() ? "is readable" : "is not readable");
     p("is " + (f1.isDirectory() ? "" : "not" + " a directory"));
     p(f1.isFile() ? "is normal file" : "might be a named pipe");
     p(f1.isAbsolute() ? "is absolute" : "is not absolute");
     p("File last modified: " + DateUtils.dateToStr(new Date(f1.lastModified()),"yyyy-MM-dd HH:mm:ss"));
     p("File size: " + f1.length() + " Bytes");

    }

运行结果

File Name: a.txt
Path: E:\workspace\a.txt
Abs Path: E:\workspace\a.txt
Parent: E:\workspace
exists
is writeable
is readable
is not a directory
is normal file
is absolute
File last modified: 2018-11-12 10:16:59
File size: 0 Bytes
 @Test
    /**
     * File对象的文件目录操作
     */
    public void test4() {
    File dir = new File("E:/workspace");
    File[] filelist = dir.listFiles();
    for (File f : filelist) {
        if (f.isFile()) {
        p("目录下的文件名:" + f.getName());
        p("目录文件的绝对路径:" + f.getAbsolutePath());
        }
    }

    File[] filelist2 = File.listRoots();
    for (File f : filelist2) {
        p("根目录下的文件名:" + f.getName());
        p("根目录文件的绝对路径:" + f.getAbsolutePath());
    }
    String[] filelist3 = dir.list();
    p("file.list()结果:===================================================");
    for (String f : filelist3) {
        p(f);
    }
    }

运行结果

目录下的文件名:a.txt
目录文件的绝对路径:E:\workspace\a.txt
根目录下的文件名:
根目录文件的绝对路径:C:\
根目录下的文件名:
根目录文件的绝对路径:D:\
根目录下的文件名:
根目录文件的绝对路径:E:\
根目录下的文件名:
根目录文件的绝对路径:F:\
根目录下的文件名:
根目录文件的绝对路径:G:\
file.list()结果:===================================================
a.txt
emacs
git
marven
myeclipse
php
python
Seafile
VMwareSpace

file.listFiles()获取目录下的所有文件与文件夹对象数组
File.listRoots()获取文件系统根目录下的所有文件与文件夹对象数组(类的静态方法)
file.list();获取目录下所有文件与文件夹名字的字符串数组

文件与文件夹的增删改

1、文件及文件夹的创建

 @Test
    /**
     * 文件及文件夹的创建
     */
    public void test7() {
    File dir = new File("E:\\workspace\\fileTest\\test");
    //创建多层目录
    dir.mkdirs();
    File file = new File("E:\\workspace\\fileTest\\test\\a.txt");
        try {
        file.createNewFile();
        } catch (IOException e) {

        e.printStackTrace();
        }
    }

mkdir是创建目录,只创建一层布存在的目录
mkdirs是创建目录,并且还会创建该目录或者文件的所有不存在的父目录。

createNewFile()必须文件的目录正确,不然出错
文件或者目录存在不会重新创建

2、文件及文件夹的删除
删除用delete方法和deleteOnExit
java中File的delete和deleteOnExit区别:

delete无需解释,为直接删除,deleteOnExit文档解释为:在虚拟机终止时,请求删除此抽象路径名表示的文件或目录。也就是说,程序运行deleteOnExit成功后,File并没有直接删除,而是在虚拟机正常运行结束后才会删除。

file创建文件的另一个方法:createTempFile(在默认临时文件目录中创建一个空文件,使用给定前缀和后缀生成其名称)

这两个方法其实是对应的,使用场景是这样的:

程序有个需求需要创建临时文件,这个临时文件可能作为存储使用,但是程序运行结束后,这个文件应该就被删除了。在哪里做删除操作呢,需要监控程序关闭吗,如果有很多地方可以中止程序,这个删除操作需要都放置一份吗?其实只要这么写,程序结束后文件就会被自动删除了:

  File file=File.createTempFile("tmp",null);
  //这里对文件进行操作
  file.deleteOnExit();

例如

@Test
    /**
     * 文件及文件夹的删除
     */
    public void test8() {
    File dir = new File("E:\\workspace\\fileTest\\test");
    //创建多层目录
    dir.mkdirs();
    File file = new File("E:\\workspace\\fileTest\\test\\b.txt");
    if(file.delete()){
        p("文件删除成功");
    }else{
        p("文件删除失败");
    }

    if(dir.delete()){
        p("目录删除成功");
    }else{
        p("目录删除失败");
    }
    }

删除不存在文件时不会报错,无法删除有子目录或者文件的文件夹,只能逐层递归删除
3、文件及文件夹的移动
boolean renameTo(File newName)

 @Test
    /**
     * 文件及文件夹的移动
     */
    public void test10() {

    File file = new File("E:\\workspace\\fileTest\\test2\\b.txt");
    if(file.renameTo(new File("E:\\workspace\\fileTest\\a.txt"))){
        p("文件移动成功");
    }else{
        p("文件移动失败");
    }
    }

4、文件及文件夹的重命名
文件和文件夹的重命名是由文件移动方法实现的

@Test
    /**
     * 文件及文件夹的重命名
     */
    public void test9() {
    File dir = new File("E:\\workspace\\fileTest\\test");
    //创建多层目录
    dir.mkdirs();
    File file = new File("E:\\workspace\\fileTest\\test\\a.txt");
    if(file.renameTo(new File("E:\\workspace\\fileTest\\test\\b.txt"))){
        p("文件重命名成功");
    }else{
        p("文件重命名失败");
    }

    if(dir.renameTo(new File("E:\\workspace\\fileTest\\test2"))){
        p("目录重命名成功");
    }else{
        p("目录重命名失败");
    }
    }

File类应用:过滤器接口FilenameFilter和FileFilter

FilenameFilter和FileFilter都是用来过滤文件,例如过滤,以.jpg或者.java结尾的文件,通过看他们的源码:通过使用File类中String[] list(FilenameFilter filter)或者public File[] listFiles(FileFilter filter)方法,把FilenameFilter或者FileFilter接口对象作为参数传入,通过实现接口里面的 boolean accept(File dir, String name) 或者boolean accept(File pathname)方法来过滤出满足条件的文件:区别:FilenameFilter的性能比FileFilter的好.

过滤器是需要实现 FilenameFilter或者FileFilter接口的类,也可以用匿名类来实现,实现accept方法即可

FilenameFilter匿名实现

 boolean accept(File dir,String name) 可以使用此方法列出指定目录下面的带有某些后缀的文件。
    参数:
    dir - 被找到的文件所在的目录。
    name - 文件的名称。
    返回:
    当且仅当该名称应该包含在文件列表中时返回 true;否则返回 false。

例如

 @Test
    /**
     * File过滤器FilenameFilter匿名实现
     */
    public void test5() {
    File dir = new File("E:/workspace");
    File[] filelist = dir.listFiles(new FilenameFilter() {

        @Override
        public boolean accept(File dir, String name) {
        if(name.endsWith("txt")){
            return true;
        }
        return false;
        }
    }

        );

    for (File f : filelist) {
        if (f.isFile()) {
        p("目录下的txt结尾文件名:" + f.getName());
        p("目录文件的绝对路径:" + f.getAbsolutePath());
        }
    }
    }

FileFilter匿名实现

 / * FileFilter接口
 * 接口方法:
 * boolean accept(File dir,String name) 可以使用此方法列出指定目录下面的带有某些后缀的文件。
    参数:
    dir - 被找到的文件所在的目录。
    name - 文件的名称。
    返回:
    当且仅当该名称应该包含在文件列表中时返回 true;否则返回 false。
 */
@Test
    /**
     * File过滤器FileFilter匿名实现
     */
    public void test6() {
    File dir = new File("E:/workspace");
    File[] filelist = dir.listFiles(new FileFilter() {

        @Override
        public boolean accept(File pathname) {
        if(pathname.getName().endsWith(".txt")){
            return true;
        }
        return false;
        }
    });

    for (File f : filelist) {
        if (f.isFile()) {
        p("目录下的txt结尾文件名:" + f.getName());
        p("目录文件的绝对路径:" + f.getAbsolutePath());
        }
    }
    }

文件过滤器不仅可以用来过滤文件类型,还可以进行其他操作,看需求自行实现

参考

深入理解JAVA I/O系列一:File

File类源码详解

Java File类方法使用详解

java基础知识回顾之javaIO类–File类应用:过滤器接口FilenameFilter和FileFilter

点赞

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注