• 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html
  • 极客专栏正式上线!欢迎访问 https://www.jikewenku.com/topic.html

Java NIO之拥抱Path和Files

技术杂谈 勤劳的小蚂蚁 3个月前 (01-24) 74次浏览 已收录 0个评论 扫描二维码

一 文件I/O基石:Path

Java7中文件IO发生了很大的变化,专门引入了很多新的类来取代原来的基于java.io.File的文件IO操作方式:
  1. import java.nio.file.DirectoryStream;
  2. import java.nio.file.FileSystem;
  3. import java.nio.file.FileSystems;
  4. import java.nio.file.Files;
  5. import java.nio.file.Path;
  6. import java.nio.file.Paths;
  7. import java.nio.file.attribute.FileAttribute;
  8. import java.nio.file.attribute.PosixFilePermission;
  9. import java.nio.file.attribute.PosixFilePermissions
  10. ......等等
我们将从下面几个方面来学习Path类:
  • 创建一个Path
  • File和Path之间的转换,File和URI之间的转换
  • 获取Path的相关信息
  • 移除Path中的冗余项

1 创建一个Path

创建Path实例可以通过 Paths工具类get()方法:
  1. //使用绝对路径
  2. Path path=Paths.get("c:\data\myfile.txt");
  1. //使用相对路径
  2. Path path =Paths.get("/home/jakobjenkov/myfile.txt");
下面这种创建方式和上面等效:
  1. Path path =FileSystems.getDefault().getPath("c:\data\myfile.txt");

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

  1.        File file =newFile("C:/my.ini");
  2.        Path p1 = file.toPath();
  3.        p1.toFile();
  4.        file.toURI();

3 获取Path的相关信息

  1.        //使用Paths工具类的get()方法创建
  2.        Path path =Paths.get("D:\XMind\bcl-java.txt");
  3. /*        //使用FileSystems工具类创建
  4.        Path path2 = FileSystems.getDefault().getPath("c:\data\myfile.txt");*/
  5.        System.out.println("文件名:"+ path.getFileName());
  6.        System.out.println("名称元素的数量:"+ path.getNameCount());
  7.        System.out.println("父路径:"+ path.getParent());
  8.        System.out.println("根路径:"+ path.getRoot());
  9.        System.out.println("是否是绝对路径:"+ path.isAbsolute());
  10.        //startsWith()方法的参数既可以是字符串也可以是Path对象
  11.        System.out.println("是否是以为给定的路径D:开始:"+ path.startsWith("D:\"));
  12.        System.out.println("该路径的字符串形式:"+ path.toString());
结果:
  1. 文件名:bcl-java.txt
  2. 名称元素的数量:2
  3. 父路径:D:XMind
  4. 根路径:D:
  5. 是否是绝对路径:true
  6. 是否是以为给定的路径D:开始:true
  7. 该路径的字符串形式:D:XMindbcl-java.txt

4 移除冗余项

某些时候在我们需要处理的Path路径中可能会有一个或两个点
  • .表示的是当前目录
  • ..表示父目录或者说是上一级目录:
下面通过实例来演示一下使用Path类的normalize()和toRealPath()方法把.和..去除。
  • normalize() : 返回一个路径,该路径是冗余名称元素的消除。
  • toRealPath() : 融合了toAbsolutePath()方法和normalize()方法
  1.        //.表示的是当前目录
  2.        Path currentDir =Paths.get(".");
  3.        System.out.println(currentDir.toAbsolutePath());//输出C:UsersAdministratorNIODemo.
  4.        Path currentDir2 =Paths.get(".\NIODemo.iml");
  5.        System.out.println("原始路径格式:"+currentDir2.toAbsolutePath());
  6.        System.out.println("执行normalize()方法之后:"+currentDir2.toAbsolutePath().normalize());
  7.        System.out.println("执行toRealPath()方法之后:"+currentDir2.toRealPath());
  8.        //..表示父目录或者说是上一级目录:
  9.        Path currentDir3 =Paths.get("..");
  10.        System.out.println("原始路径格式:"+currentDir3.toAbsolutePath());
  11.        System.out.println("执行normalize()方法之后:"+currentDir3.toAbsolutePath().normalize());
  12.        System.out.println("执行toRealPath()方法之后:"+currentDir3.toRealPath());
结果:
  1. C:UsersAdministratorNIODemo.
  2. 原始路径格式:C:UsersAdministratorNIODemo.NIODemo.iml
  3. 执行normalize()方法之后:C:UsersAdministratorNIODemoNIODemo.iml
  4. 执行toRealPath()方法之后:C:UsersAdministratorNIODemoNIODemo.iml
  5. 原始路径格式:C:UsersAdministratorNIODemo..
  6. 执行normalize()方法之后:C:UsersAdministrator
  7. 执行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() 检测文件路径是否存在:
  1.       Path path =Paths.get("D:\XMind\bcl-java.txt");
  2.        boolean pathExists =
  3.                Files.exists(path,
  4.                        newLinkOption[]{LinkOption.NOFOLLOW_LINKS});
  5.        System.out.println(pathExists);//true
注意Files.exists()的的第二个参数。它是一个数组,这个参数直接影响到Files.exists()如何确定一个路径是否存在。在本例中,这个数组内包含了LinkOptions.NOFOLLOW_LINKS,表示检测时不包含符号链接文件。

2 创建文件/文件夹

创建文件:
通过 Files.createFile() 创建文件,
  1.        Path target2 =Paths.get("C:\mystuff.txt");
  2.        try{
  3.            if(!Files.exists(target2))
  4.                Files.createFile(target2);
  5.        }catch(IOException e){
  6.            e.printStackTrace();
  7.        }
创建文件夹:
Files.createDirectories()会首先创建所有不存在的父目录来创建目录,而Files.createDirectory()方法只是创建目录,如果它的上级目录不存在就会报错。比如下面的程序使用Files.createDirectory() 方法创建就会报错,这是因为我的D盘下没有data文件夹,加入存在data文件夹的话则没问题。
通过 Files.createDirectory() 创建文件夹
通过 Files.createDirectories() 创建文件夹
  1.        Path path =Paths.get("D://data//test");
  2.        try{
  3.            Path newDir =Files.createDirectories(path);
  4.        }catch(FileAlreadyExistsException e){
  5.            // the directory already exists.
  6.        }catch(IOException e){
  7.            //something else went wrong
  8.            e.printStackTrace();
  9.        }

3 删除文件或目录

通过 Files.delete()方法 可以删除一个文件或目录:
  1. Path path =Paths.get("data/subdir/logging-moved.properties");
  2. try{
  3.    Files.delete(path);
  4. }catch(IOException e){
  5.    //deleting file failed
  6.    e.printStackTrace();
  7. }

4 把一个文件从一个地址复制到另一个位置

通过Files.copy()方法可以吧一个文件从一个地址复制到另一个位置
  1. Path sourcePath      =Paths.get("data/logging.properties");
  2. Path destinationPath =Paths.get("data/logging-copy.properties");
  3. try{
  4.    Files.copy(sourcePath, destinationPath);
  5. }catch(FileAlreadyExistsException e){
  6.    //destination file already exists
  7. }catch(IOException e){
  8.    //something else went wrong
  9.    e.printStackTrace();
  10. }
copy操作还可可以强制覆盖已经存在的目标文件,只需要将上面的copy()方法改为如下格式:
  1.    Files.copy(sourcePath, destinationPath,
  2.            StandardCopyOption.REPLACE_EXISTING);

5 获取文件属性

  1.        Path path =Paths.get("D:\XMind\bcl-java.txt");
  2.        System.out.println(Files.getLastModifiedTime(path));
  3.        System.out.println(Files.size(path));
  4.        System.out.println(Files.isSymbolicLink(path));
  5.        System.out.println(Files.isDirectory(path));
  6.        System.out.println(Files.readAttributes(path,"*"));
结果:
  1. 2016-05-18T08:01:44Z
  2. 18934
  3. false
  4. false
  5. {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 遍历一个文件夹

  1.        Path dir =Paths.get("D:\Java");
  2.        try(DirectoryStream<Path> stream =Files.newDirectoryStream(dir)){
  3.            for(Path e : stream){
  4.                System.out.println(e.getFileName());
  5.            }
  6.        }catch(IOException e){
  7.        }
结果:
  1. apache-maven-3.5.0
  2. Eclipse
  3. intellij idea
  4. Jar
  5. JDK
  6. MarvenRespository
  7. MyEclipse2017 CI
  8. Nodejs
  9. RedisDesktopManager
  10. solr-7.2.1
上面是遍历单个目录,它不会遍历整个目录。遍历整个目录需要使用:Files.walkFileTree().Files.walkFileTree()方法具有递归遍历目录的功能。

7 遍历整个文件目录:

walkFileTree接受一个Path和FileVisitor作为参数。Path对象是需要遍历的目录,FileVistor则会在每次遍历中被调用。
FileVisitor需要调用方自行实现,然后作为参数传入walkFileTree().FileVisitor的每个方法会在遍历过程中被调用多次。如果不需要处理每个方法,那么可以继承它的默认实现类SimpleFileVisitor,它将所有的接口做了空实现。
  1. publicclassWorkFileTree{
  2.    publicstaticvoid main(String[] args)throwsIOException{
  3.        Path startingDir =Paths.get("D:\apache-tomcat-9.0.0.M17");
  4.        List<Path> result =newLinkedList<Path>();
  5.        Files.walkFileTree(startingDir,newFindJavaVisitor(result));
  6.        System.out.println("result.size()="+ result.size());
  7.    }
  8.    privatestaticclassFindJavaVisitorextendsSimpleFileVisitor<Path>{
  9.        privateList<Path> result;
  10.        publicFindJavaVisitor(List<Path> result){
  11.            this.result = result;
  12.        }
  13.        @Override
  14.        publicFileVisitResult visitFile(Path file,BasicFileAttributes attrs){
  15.            if(file.toString().endsWith(".java")){
  16.                result.add(file.getFileName());
  17.            }
  18.            returnFileVisitResult.CONTINUE;
  19.        }
  20.    }
  21. }
上面这个例子输出了我的D:apache-tomcat-9.0.0.M17也就是我的Tomcat安装目录下以.java结尾文件的数量。
结果:
  1. result.size()=4
Files类真的很强大,除了我讲的这些操作之外还有其他很多操作比如:读取和设置文件权限、更新文件所有者等等操作。
我这里就介绍这么多了,如果想要详细了解的可以自行查阅官方文档或者相关书籍。
谷歌搜索排名第一的Java NIO教程:http://tutorials.jenkov.com/java-nio/channels.html
《Java程序员修炼之道》:https://book.douban.com/subject/24841235/
《Java 8编程官方参考教程(第9版)》:https://book.douban.com/subject/26320992/
Java7新特性之文件操作:http://www.cnblogs.com/digdeep/p/4478734.html

丨极客文库, 版权所有丨如未注明 , 均为原创丨
本网站采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行授权
转载请注明原文链接:Java NIO之拥抱Path和Files
喜欢 (0)
[247507792@qq.com]
分享 (0)
勤劳的小蚂蚁
关于作者:
温馨提示:本文来源于网络,转载文章皆标明了出处,如果您发现侵权文章,请及时向站长反馈删除。

您必须 登录 才能发表评论!

  • 精品技术教程
  • 编程资源分享
  • 问答交流社区
  • 极客文库知识库

客服QQ


QQ:2248886839


工作时间:09:00-23:00