资讯专栏INFORMATION COLUMN

Java NIO之拥抱Path和Files

DevYK / 2289人阅读

摘要:返回一个路径,该路径是冗余名称元素的消除。本节教程将覆盖大部分方法。在本例中,这个数组内包含了,表示检测时不包含符号链接文件。遍历整个文件目录接受一个和作为参数。

Java面试通关手册(Java学习指南)github地址(欢迎star和pull):https://github.com/Snailclimb/Java_Guide

历史回顾:

Java NIO 概览

Java NIO 之 Buffer(缓冲区)

Java NIO 之 Channel(通道)

Java NIO之Selector(选择器)

其他高赞文章:

面试中关于Redis的问题看这篇就够了

一文轻松搞懂redis集群原理及搭建与使用

超详细的Java面试题总结(三)之Java集合篇常见问题

一 文件I/O基石:Path

Java7中文件IO发生了很大的变化,专门引入了很多新的类来取代原来的基于java.io.File的文件IO操作方式:

import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;·

......等等

我们将从下面几个方面来学习Path类:

创建一个Path

File和Path之间的转换,File和URI之间的转换

获取Path的相关信息

移除Path中的冗余项

1 创建一个Path

创建Path实例可以通过 Paths工具类get()方法:

//使用绝对路径
 Path path= Paths.get("c:datamyfile.txt");
//使用相对路径
Path path = Paths.get("/home/jakobjenkov/myfile.txt");

下面这种创建方式和上面等效:

Path path = FileSystems.getDefault().getPath("c:datamyfile.txt");
2 File和Path之间的转换,File和URI之间的转换
        File file = new File("C:/my.ini");
        Path p1 = file.toPath();
        p1.toFile();
        file.toURI();
3 获取Path的相关信息
        //使用Paths工具类的get()方法创建
        Path path = Paths.get("D:XMindcl-java.txt");
/*        //使用FileSystems工具类创建
        Path path2 = FileSystems.getDefault().getPath("c:datamyfile.txt");*/
        System.out.println("文件名:" + path.getFileName());
        System.out.println("名称元素的数量:" + path.getNameCount());
        System.out.println("父路径:" + path.getParent());
        System.out.println("根路径:" + path.getRoot());
        System.out.println("是否是绝对路径:" + path.isAbsolute());
        //startsWith()方法的参数既可以是字符串也可以是Path对象
        System.out.println("是否是以为给定的路径D:开始:" + path.startsWith("D:") );
        System.out.println("该路径的字符串形式:" + path.toString());

结果:

文件名:bcl-java.txt
名称元素的数量:2
父路径:D:XMind
根路径:D:
是否是绝对路径:true
是否是以为给定的路径D:开始:true
该路径的字符串形式:D:XMindcl-java.txt
4 移除冗余项

某些时候在我们需要处理的Path路径中可能会有一个或两个点

.表示的是当前目录

..表示父目录或者说是上一级目录:

下面通过实例来演示一下使用Path类的normalize()和toRealPath()方法把.和..去除。

normalize() : 返回一个路径,该路径是冗余名称元素的消除。

toRealPath() : 融合了toAbsolutePath()方法和normalize()方法

        //.表示的是当前目录
        Path currentDir = Paths.get(".");
        System.out.println(currentDir.toAbsolutePath());//输出C:UsersAdministratorNIODemo.
        Path currentDir2 = Paths.get(".NIODemo.iml");
        System.out.println("原始路径格式:"+currentDir2.toAbsolutePath());
        System.out.println("执行normalize()方法之后:"+currentDir2.toAbsolutePath().normalize());
        System.out.println("执行toRealPath()方法之后:"+currentDir2.toRealPath());

        //..表示父目录或者说是上一级目录:
        Path currentDir3 = Paths.get("..");
        System.out.println("原始路径格式:"+currentDir3.toAbsolutePath());
        System.out.println("执行normalize()方法之后:"+currentDir3.toAbsolutePath().normalize());
        System.out.println("执行toRealPath()方法之后:"+currentDir3.toRealPath());

结果:

C:UsersAdministratorNIODemo.
原始路径格式:C:UsersAdministratorNIODemo.NIODemo.iml
执行normalize()方法之后:C:UsersAdministratorNIODemoNIODemo.iml
执行toRealPath()方法之后:C:UsersAdministratorNIODemoNIODemo.iml
原始路径格式:C:UsersAdministratorNIODemo..
执行normalize()方法之后:C:UsersAdministrator
执行toRealPath()方法之后:C:UsersAdministrator

二 拥抱Files类

Java NIO中的Files类(java.nio.file.Files)提供了多种操作文件系统中文件的方法。本节教程将覆盖大部分方法。Files类包含了很多方法,所以如果本文没有提到的你也可以直接查询JavaDoc文档。

java.nio.file.Files类是和java.nio.file.Path相结合使用的

1 检查给定的Path在文件系统中是否存在

通过 Files.exists() 检测文件路径是否存在:

       Path path = Paths.get("D:XMindcl-java.txt");

        boolean pathExists =
                Files.exists(path,
                        new LinkOption[]{LinkOption.NOFOLLOW_LINKS});
        System.out.println(pathExists);//true

注意Files.exists()的的第二个参数。它是一个数组,这个参数直接影响到Files.exists()如何确定一个路径是否存在。在本例中,这个数组内包含了LinkOptions.NOFOLLOW_LINKS,表示检测时不包含符号链接文件。

2 创建文件/文件夹

创建文件:

通过 Files.createFile() 创建文件,

        Path target2 = Paths.get("C:mystuff.txt");
        try {
            if(!Files.exists(target2))
                Files.createFile(target2);
        } catch (IOException e) {
            e.printStackTrace();
        }

创建文件夹:

通过 Files.createDirectory() 创建文件夹

通过 Files.createDirectories() 创建文件夹

Files.createDirectories()会首先创建所有不存在的父目录来创建目录,而Files.createDirectory()方法只是创建目录,如果它的上级目录不存在就会报错。比如下面的程序使用Files.createDirectory() 方法创建就会报错,这是因为我的D盘下没有data文件夹,加入存在data文件夹的话则没问题。

    Path path = Paths.get("D://data//test");

    try {
        Path newDir = Files.createDirectories(path);
    } catch(FileAlreadyExistsException e){
        // the directory already exists.
    } catch (IOException e) {
        //something else went wrong
        e.printStackTrace();
    }
3 删除文件或目录

通过 Files.delete()方法 可以删除一个文件或目录:

Path path = Paths.get("data/subdir/logging-moved.properties");

try {
    Files.delete(path);
} catch (IOException e) {
    //deleting file failed
    e.printStackTrace();
}
4 把一个文件从一个地址复制到另一个位置

通过Files.copy()方法可以吧一个文件从一个地址复制到另一个位置

Path sourcePath      = Paths.get("data/logging.properties");
Path destinationPath = Paths.get("data/logging-copy.properties");

try {
    Files.copy(sourcePath, destinationPath);
} catch(FileAlreadyExistsException e) {
    //destination file already exists
} catch (IOException e) {
    //something else went wrong
    e.printStackTrace();
}

copy操作还可可以强制覆盖已经存在的目标文件,只需要将上面的copy()方法改为如下格式:

    Files.copy(sourcePath, destinationPath,
            StandardCopyOption.REPLACE_EXISTING);
5 获取文件属性
        Path path = Paths.get("D:XMindcl-java.txt");
        System.out.println(Files.getLastModifiedTime(path));
        System.out.println(Files.size(path));
        System.out.println(Files.isSymbolicLink(path));
        System.out.println(Files.isDirectory(path));
        System.out.println(Files.readAttributes(path, "*"));

结果:

2016-05-18T08:01:44Z
18934
false
false
{lastAccessTime=2017-04-12T01:42:21.149351Z, lastModifiedTime=2016-05-18T08:01:44Z, size=18934, creationTime=2017-04-12T01:42:21.149351Z, isSymbolicLink=false, isRegularFile=true, fil
6 遍历一个文件夹
        Path dir = Paths.get("D:Java");
        try(DirectoryStream stream = Files.newDirectoryStream(dir)){
            for(Path e : stream){
                System.out.println(e.getFileName());
            }
        }catch(IOException e){

        }

结果:

apache-maven-3.5.0
Eclipse
intellij idea
Jar
JDK
MarvenRespository
MyEclipse 2017 CI
Nodejs
RedisDesktopManager
solr-7.2.1

上面是遍历单个目录,它不会遍历整个目录。遍历整个目录需要使用:Files.walkFileTree().Files.walkFileTree()方法具有递归遍历目录的功能。

7 遍历整个文件目录:

walkFileTree接受一个Path和FileVisitor作为参数。Path对象是需要遍历的目录,FileVistor则会在每次遍历中被调用。

FileVisitor需要调用方自行实现,然后作为参数传入walkFileTree().FileVisitor的每个方法会在遍历过程中被调用多次。如果不需要处理每个方法,那么可以继承它的默认实现类SimpleFileVisitor,它将所有的接口做了空实现。

public class WorkFileTree {

    public static void main(String[] args) throws IOException{
        Path startingDir = Paths.get("D:apache-tomcat-9.0.0.M17");
        List result = new LinkedList();
        Files.walkFileTree(startingDir, new FindJavaVisitor(result));
        System.out.println("result.size()=" + result.size());
    }

    private static class FindJavaVisitor extends SimpleFileVisitor{
        private List result;
        public FindJavaVisitor(List result){
            this.result = result;
        }
        @Override
        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs){
            if(file.toString().endsWith(".java")){
                result.add(file.getFileName());
            }
            return FileVisitResult.CONTINUE;
        }
    }
}

上面这个例子输出了我的D:apache-tomcat-9.0.0.M17也就是我的Tomcat安装目录下以.java结尾文件的数量。

结果:

result.size()=4

Files类真的很强大,除了我讲的这些操作之外还有其他很多操作比如:读取和设置文件权限、更新文件所有者等等操作。

我这里就介绍这么多了,如果想要详细了解的可以自行查阅官方文档或者相关书籍。

官方JDK相关文档

谷歌搜索排名第一的Java NIO教程

《Java程序员修炼之道》

《Java 8编程官方参考教程(第9版)》

Java7新特性之文件操作

欢迎关注我的微信公众号:"Java面试通关手册"(一个有温度的微信公众号,期待与你共同进步~~~坚持原创,分享美文,分享各种Java学习资源):

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69397.html

相关文章

  • 关于Java IO与NIO知识都在这里

    摘要:从通道进行数据写入创建一个缓冲区,填充数据,并要求通道写入数据。三之通道主要内容通道介绍通常来说中的所有都是从通道开始的。从中选择选择器维护注册过的通道的集合,并且这种注册关系都被封装在当中停止选择的方法方法和方法。 由于内容比较多,我下面放的一部分是我更新在我的微信公众号上的链接,微信排版比较好看,更加利于阅读。每一篇文章下面我都把文章的主要内容给列出来了,便于大家学习与回顾。 Ja...

    Riddler 评论0 收藏0
  • JAVA NIO.2

    摘要:会自动遍历下的所有文件和目录,并对其触发中相应的方法,并使用方法的返回值来控制访问器的后续行为。它的实例有继续不访问兄弟文件或目录不访问子文件或子目录终止后续行为官网实例删除所有子文件和子目录是一个接口,定义了监听目录变化的方法。 简介 java 7新增了如下API来访问文件或者进行IO操作 Path - 接口,代表一个平台无关的目录。提供了大量的方法来操作目录。 Paths - ...

    TerryCai 评论0 收藏0
  • 解决Docker Machine中的容器文件不能持久的问题

    摘要:解决中的容器文件不能持久的问题目前下使用的主流方式还是使用需要借用虚拟器启动一个宿主机才能在上面启动多个容器当我们在容器中运行服务时经常会有需要将服务数据持久化的场景比如运行集群时需要将索引数据持久保存到磁盘那具体保存到哪里呢容器的无状态特 解决Docker Machine中的容器文件不能持久的问题 目前Mac下使用docker的主流方式还是使用Docker machine. Dock...

    Amio 评论0 收藏0
  • Java JDK11中的新API

    摘要:将参数的所有字节写入输出流两个允许指定的新构造函数。四个允许指定的新构造函数。返回从此字符串中提取的行的流,由行终止符分隔。如上所述,使用指定的将字符编码为字节。返回此表示的执行客户端中的包装原因,如果原因不存在或未知,则返回。 有关API更改的完整列表,可在Github上获得。 这里列出的是除了java.net.http和jdk.jfr模块之外的所有新方法。没有列出java.secu...

    pepperwang 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<