`
AsWater
  • 浏览: 24768 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Java SE 7 新特性之文件操作(2)- Path类的基本操作

 
阅读更多

转自开发者的天空

在上面的一篇文章中,我们已经说过了Path 类的操作主要有两种:对路径的操作和对文件的操 作。这篇文章中我们就来了解一下对路径的操作。
创建Path实例
Path实例包含了指定文件或目录位置的信息,在实例化Path类时,需要指定一个或多个目录或文件名。路径的根目录不是必须的;路径信息可能仅仅是一个 目录或文件的名称。
最简单的创建Path实例的方式就是使用Paths(注意这里有一个s)类的get方法:

  1.         Path p1 = Paths.get("/tmp/foo");
  2.         Path p2 = Paths.get(args[0]);
  3.         Path p3 = Paths.get("file:///Users/joe/FileTest.java");
复制代码

Path类接受String或URI作为参数。

获取路径信息
前面我们已经说过了,File System一般是树形结构,因此我们可以把Path理解为按顺序存储的一系列的名称(目录名称和文件名称)。目录结构中最高一层的目录名就是序列中 index为0的那一个,目录结构中最低一层的目录名或者文件名就是序列中index为n-1的那一个(这里n是路径中层次的数目)。Path类提供方法 来通过index获取序列中的一个元素或一个子序列。
随后的例子中我们使用的目录结构如下图:
io-dirStructure.JPG



    下面的代码定义了一个Path对象并获取其中的信息。要注意的是这些代码中除了isHidden方法外,其他的方法并不需要指定的目录或文件存在;如果不 存在,isHidden方法会抛出异常。

  1.         Path path = Paths.get("C:\\home\\joe\\foo");    // Microsoft Windows syntax
  2.         //Path path = Paths.get("/home/joe/foo");    // Solaris syntax
  3.         System.out.format("toString: %s%n", path.toString());
  4.         System.out.format("getName: %s%n", path.getName());
  5.         System.out.format("getName(0): %s%n", path.getName(0));
  6.         System.out.format("getNameCount: %d%n", path.getNameCount());
  7.         System.out.format("subpath(0,2): %d%n", path.subpath(0,2));
  8.         System.out.format("getParent: %s%n", path.getParent());
  9.         System.out.format("getRoot: %s%n", path.getRoot());
  10.         System.out.format("isHidden: %s%n", path.isHidden());
复制代码

下面是这段代码的输出情况

方法 Solaris下的输出 Windows下的 输出 备注
toString /home/joe/foo C:\home\joe\foo
getName foo foo 获 取名称序列中的最后一个,也就是最底层的目录或文件名
getName(0) home home 获 取名称序列中的第一个,也就是最靠近根目录的那一层。注意根目录不在名称序列中
getNameCount 3 3 获 取名称序列的元素个数
subpath(0,2) home/joe home\joe 获 取从指定的开始点到指定的结束点的子路径。注意这里包括开始点,但不包括结束点。
getParent /home/joe \home\joe 返 回Path指定的目录或文件的父目录
getRoot / C:\ 返 回根目录
isHidden false false 如果文件是 隐藏文件,或者目录是隐藏目录,返回true。因为要访问文件的属性,所以如果Path指定的目录或者文件不存在,会抛出异常。



上面的代码中我们创建Path时使用的是绝对路径,下面我们来看看创建路径时使用相对路径时,这段代码的执行结果:

  1.         //Path path = Paths.get("sally/bar");     // Solaris syntax
  2.         Path path = Paths.get("sally\\bar");    // Microsoft Windows syntax
复制代码

大 家可以自行去实验一下具体的输出是什么。

去除Path中的冗余
在很多文件系统中我们使用'.'来代表当前目录,使用'..'代表父目录。在有些情况下我们创建的路径中会有冗余的路径信息,例如:
        /home/./joe/foo
        /home/sally/../joe/foo
方法normalize会去除这些冗余信息,包括'.'或'directory/..'。上面的两个例子在去除冗余信息后都是/home/joe /foo。
要注意的是normalize方法并不去检查文件系统,它只是简单的进行语法操作。在第二个例子中,如果sally是一个指向其他的目录的符号链接,那么 去除了sally/..后可能导致Path不在指向原来的文件或目录。
如果你需要清除冗余信息,又要保证结果仍然指向正确的文件或目录,可以使用toRealPath方法。在下面我们会讲到这个方法。
转换Path
有3个方法用来转换Path。

  • toUri方法
    如果你需要将Path转换为可以在浏览器中打开的字符串格式,可以使用toUri方法,例如:
    1.         Path p1 = Paths.get("/home/logfile");
    2.         System.out.format("%s%n", p1.toUri());  // 结果是 file:///home/logfile
    复 制代码
    注意在这里即使/home/logfile'指向的目录或文件不存在,这段代码同样能够执行成功。
  • toAbsolutePath 方法
    该方法将路径转换为绝对路径。如果原来的Path已经是绝对路径,该方法直接返回原有的Path对象。
    我们来看看下面的例子:
    1.                 Path path = Paths.get("home\\joe\\foo");
    2.                 Path absolutePath = path.toAbsolutePath();
    3.                 System.out.println(path == absolutePath); //结果是false
    4.                
    5.                 Path path2 = Paths.get("c:\\home\\joe\\foo ");
    6.                 Path absolutePath2 = path2.toAbsolutePath();
    7.                 System.out.println(path2 == absolutePath2);//结果是true
    复制代码
    同样的,toAbsolutePath方法并不需要 Path所指向的文件或目录存在。
  • toRealPath方法
    这个方法会返回一个已经存在的文件或目录的真实路径(如果文件或目录不存在或无法访问,该方法会抛出异常)。该方法会执行以下的操作:
    如果传入的参数是true并且文件系统支持符号链接,则解析路径中存在的符号链接(如果有的话)。
    如果原来的Path是相对路径,将其转换成绝对路径。
    如果路径中含有冗余信息,返回的Path中这些冗余信息会被去除。


连接两个Path
可以使用resolve方法来将两个Path连接起来。该方法的参数是一个字符串。如果该字符串代表的是一个相对路径,那么这个路径会被扩展到原来的路径 后。如果传入的字符串是一个绝对路径,那么返回的值就是传入的这个绝对路径。例如:

  1.         Path p1 = Paths.get("C:\\home\\joe\\foo");   
  2.         System.out.format("%s%n", p1.resolve("bar")); // 结果是 C:\home\joe\foo\bar

  3.         Paths.get("foo").resolve("c:\\home\joe");       // 结果是  C:\home\joe
复制代码

创建两个路径之间的路径
这个功能说起来有些绕口,实际的功能就是创建两个指定的目录或文件之间的相对路径。例如:

  1.         Path p1 = Paths.get("joe/foo");
  2.         Path p2 = Paths.get("sally");
复制代码

在这个例子中,由于两个路径都是相对路径,没有其他的 信息,我们会认为这两个joe和sally是同一级的兄弟目录,因此有以下的结果

  1.         Path p1_to_p2 = p1.relativize(p2);   // 结果是 ../../sally
  2.         Path p2_to_p1 = p2.relativize(p1);   // 结果是 ../joe/foo
复制代码

让我们看看另外一个例子:

  1.         Path p1 = Paths.get("home");
  2.         Path p3 = Paths.get("home/sally/bar");
  3.         Path p1_to_p3 = p1.relativize(p3);  // 结果是 sally/bar
  4.         Path p3_to_p1 = p3.relativize(p1);  // 结果是 ../..
复制代码

在这个例子中,两个路径共享同一个节点-home, 所以结果并不是../home/sally/bar和../../../home.
如果两个路径中有一个是绝对路径,另外一个是相对路径,relative方法会抛出异常。如果两个路径都是绝对路径,那么relative方法的行为和系 统相关,不同的系统可能不同。
我在Windows操作系统下实验了一下,如果两个路径属于同一个硬盘,那么可以执行成功,否则会抛出异常。

  1. Path path1 = Paths.get("c:\\abcd\\efg");
  2. Path path2 = Paths.get("c:\\temp");
  3. System.out.println(path1.relativize(path2));        //结果是..\..\temp
  4. System.out.println(path2.relativize(path1));        //结果是..\abcd\efg

  5. Path path3 = Paths.get("c:\\abcd\\efg");
  6. Path path4 = Paths.get("d:\\temp");
  7. System.out.println(path3.relativize(path4));        //抛出异常
复制代码

Path 的比较
Path提供equals 方法来检查两个Path是否相等。但是这里 要注意的是比较的并不是两个Path是否指向同一个目录或者文件。请看下面的例子:

  1. Path path1 = Paths.get("abcd\\123");
  2. Path path2 = Paths.get("abcd\\123");
  3. Path path3 = Paths.get("abcd\\.\\123");
  4. System.out.println(path1.equals(path2));        //true
  5. System.out.println(path1.equals(path3));        //false
  6. System.out.println(path1.equals(path3.normalize())); //true
  7. System.out.println(path1.equals(path1.toAbsolutePath()));        //false
复制代码

Path 类还提供了startsWith和endsWith方法,这两个方法用来检查路径是否以指定的字符串开始或者结束,例如:

  1.         Path path = ...;
  2.         Path otherPath = ...;
  3.         Path beginning = Paths.get("/home");
  4.         Path ending = Paths.get("foo");

  5.         if (path.equals(otherPath)) {
  6.             //equality logic here
  7.         } else if (path.startsWith(beginning)) {
  8.             //path begins with "/home"
  9.         } else if (path.endsWith(ending)) {
  10.             //path ends with "foo"
  11.         }
复 制代码

Path类实现了Iterable接口,iterator方法会返回一个Iterator对象,该对象中的第一个元素就是原 路径中最上层(最靠近根节点)的目录。下面是使用这个方法的例子:

  1.         Path path = ...;
  2.         for (Path name: path) {
  3.             System.out.println(name);
  4.         }
复 制代码

Path类还实现了Comparable接口,因此可以使用compareTo来比较两个Path。比较的算法和结果是和文 件系统的提供者和系统平台相关的。大家在使用之前,最后先实验一下。
Path类还提供了一个方法isSameFile来检查两个Path是否指向同一个目录或文件。如果作为参数的Path为null,那么会直接返回 false,不会去检查Path指向的文件是否存在。如果两Path来自不同的文件系统提供者,那么也会直接返回false,不会去检查文件或目录是否存 在。如果两个Path执行equals方法的返回结果为true,那么这个方法直接返回true,也不会去检查文件或目录是否存在。其他的情况下是否会去 打开或访问Path指向的文件或目录是与具体的实现相关的,也就是说不同的JDK/JRE可能会有不同的行为。
验证文件或目录是否存在
上面所介绍的很多方法都不会去验证Path指向的文件或目录是否存在,只是操作Path实例自身。但是在有些情况下,你 需要访问文件系统来验证文件、目录存在与否,这时你可以使用exists和notExists方法。需要注意的是!path.exists()并不等于 path.notExists()。当你调用这两个方法时,有以下3中情况:

  • 文件或者目录被证实存在
  • 文件或者目录被证实不存在
  • 不知道文件或目录是否存在。当程序没有访问这个文 件或目录的权限的时候这个情况会发生。


如果exists()和notExists()都返回false,说明无法验证该文件是否存在。

在下面一篇文章中,我们会介绍怎样进行文件的操作。

分享到:
评论
1 楼 abtccb 2012-05-10  
Path是接口罢,怎么可以调用它的方法呢?
Path path = Paths.get("home\\joe\\foo");
Path absolutePath = path.toAbsolutePath();
请解答。

相关推荐

    Java SE 7 Documentation

    9. **文件系统API增强**:Java 7提供了新的`java.nio.file`包,包含`Path`、`Files`和`FileSystem`接口,提供了对文件系统的强大操作和支持。 10. **改进的并发工具**:Java 7中并发包`java.util.concurrent`增加了...

    Java虚拟机规范(Java SE 7 中文版

    7. 文件系统API增强:Java 7引入了新的`java.nio.file`包,提供了一组与平台无关的文件系统操作,如Path接口、Files类和Files API,增强了文件操作的能力。 8. NIO.2:Java SE 7扩展了非阻塞I/O(New I/O)框架,...

    Java SE 14 Linux安装包

    Java SE 14是Oracle公司发布的第14个主要版本,它包含了一系列的新特性、改进和性能优化,旨在提高开发效率和程序性能。在这个场景中,我们讨论的是Java SE 14针对Linux操作系统的安装包。 首先,Java的跨平台特性...

    jdk-1.7-java-7-openjdk-amd64.zip

    4. **文件API增强**:引入了`java.nio.file`包,提供了更强大、更易用的文件操作接口,支持Path、Files和Paths类等。 5. **try-with-resources**:一种新的资源管理方式,自动关闭在try语句块中打开的资源,如输入/...

    OCA Java SE7 Programmer I认证学习指南(Exam 1Z0-803).rar

    Java SE 7引入了许多新功能和改进,包括: 1. 多 catch 语句:在处理异常时,可以使用一个catch块同时捕获多种类型的异常,提高了代码的简洁性。 2. 针对try-catch-finally的改进:try块可以包含多个资源,这些资源...

    java-7-openjdk-amd64.tar.gz

    这个版本对于在Linux操作系统上编译Android 5.1源码特别有用,因为Android 5.1的开发环境通常依赖于Java 7的SDK或OpenJDK。 首先,让我们深入理解Java OpenJDK。OpenJDK是一个开放源代码项目,由甲骨文公司(Oracle)...

    JAVA SE基础题

    ### JAVA SE基础题知识点解析 #### 1. JDK与JRE - **JDK**: Java Development Kit,即Java开发工具包。它包含了编译、调试和运行Java应用程序所需的工具和文档,是Java开发者进行Java应用开发的基础。 - **JRE**: ...

    Java SE API 1.7 英文版(lang)

    新的非阻塞I/O API(New I/O 2,即NIO.2)引入了Path类,FileChannel和AsynchronousFileChannel的改进,以及文件系统查询的能力,极大地提升了文件操作的效率和灵活性。 8. **文件属性API**: Java 7提供了一组新...

    Java SE Development Kit 8

    下载并安装这个文件后,开发者可以在Windows环境下设置Java开发环境,包括Java编译器(javac)、Java解释器(java)和其他开发工具,从而开始使用Java 8的新特性进行开发工作。记得在安装后配置系统环境变量,确保...

    Java-SE 罗召勇的pdf

    Java-SE 罗召勇的PDF教程是一个适合初学者的Java Standard Edition(Java SE)学习资源,它包含了多个章节,旨在帮助用户从基础开始掌握Java编程语言。本教程覆盖了从Java的基础语法到更高级的概念,通过例题和代码...

    Windows Java SE Development Kit 11.0.15.1 x64 Installer

    在Java SE Development Kit 11.0.15.1版本中,我们看到的是一个针对64位操作系统的安装程序,这对于我们理解Java开发环境的构建至关重要。 首先,Java SE,全称为Java Standard Edition,是Java平台的一个主要分支...

    Java SE (jdk1.8下载 64位).rar

    Java SE(标准版)是Java开发工具包的一个版本,主要用于桌面应用和服务器端应用程序的开发。JDK(Java Development Kit)是Java编程语言的核心组成部分,它包含了一个Java编译器、Java运行时环境(JRE)、调试工具...

    Java se 课件,pdf

    Java SE作为Java技术的基础部分,涵盖了从基本语法到高级特性的一系列重要内容。通过系统学习Java SE,不仅可以掌握扎实的编程基础,还能深入了解Java语言的特点和优势。无论是对于初学者还是有一定经验的开发者来说...

    jdk1.8.0_144 (Java SE Development Kit 8u144)

    **Java SE Development Kit 8u144 (JDK 1.8.0_144)** **一、Java JDK概述** Java Standard Edition (SE) Development Kit 是Oracle公司提供的用于开发和部署Java应用程序的基础工具集。JDK是Java开发环境的核心...

    java-SE-马士兵笔记word

    ### Java SE - 马士兵笔记精要 ...以上内容覆盖了Java SE的基础知识和技术要点,包括语言特性、基本语法以及面向对象编程的核心概念。这对于初学者来说是非常重要的基础知识,也是后续深入学习Java技术栈的基石。

    Java SE 11 Linux安装包

    本安装包是Oracle公司为Linux操作系统提供的Java SE 11版本,确保了开发者在Linux环境下能够进行Java程序的开发和运行。 在Linux系统中安装Java SE 11通常涉及以下几个步骤: 1. **下载**:首先,你需要访问Oracle...

    Java SE 8u251 Linux安装包

    Java SE 8引入了一些重要的新特性,比如Lambda表达式,它简化了处理函数式编程任务的方式;新的日期和时间API(java.time包)提供了更强大和灵活的日期处理功能;方法引用和默认方法增强了接口的使用。此外,还增强...

    java9新特性

    Java 9 作为 Java 平台标准版(Java SE)的一个重要版本,在 2017 年 7 月正式发布。这一版本引入了许多令人兴奋的新特性,这些新特性不仅提高了开发效率,还增强了应用程序的性能和可维护性。下面我们将详细介绍 ...

    Java SE帮助文档(从5到8的英文版)

    多路复用文件系统(Path API)和文件属性API简化了文件操作。还有新的类型推断机制,使得编译器能更智能地推断局部变量的类型。此外,还增加了钻石操作符()来简化无参构造器的实例化。 4. **Java 8 API**: Java...

Global site tag (gtag.js) - Google Analytics