`
developersky
  • 浏览: 7944 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
社区版块
存档分类
最新评论

Java SE 7文件操作之路径操作

阅读更多
Java SE 7中对Path类的操作主要有两种:对路径的操作和对文件的操作。这篇文章中我们就来了解一下对路径的操作。

创建Path实例
Path实例包含了指定文件或目录位置的信息,在实例化Path类时,需要指定一个或多个目录或文件名。路径的根目录不是必须的;路径信息可能仅仅是一个目录或文件的名称。
最简单的创建Path实例的方式就是使用Paths(注意这里有一个s)类的get方法:

            Path p1 = Paths.get("/tmp/foo");
            Path p2 = Paths.get(args[0]);
            Path p3 = Paths.get("file:///Users/joe/FileTest.java");

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

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

    下面的代码定义了一个Path对象并获取其中的信息。要注意的是这些代码中除了isHidden方法外,其他的方法并不需要指定的目录或文件存在;如果不存在,isHidden方法会抛出异常。
            Path path = Paths.get("C:\\home\\joe\\foo");    // Microsoft Windows syntax
            //Path path = Paths.get("/home/joe/foo");    // Solaris syntax
            System.out.format("toString: %s%n", path.toString());
            System.out.format("getName: %s%n", path.getName());
            System.out.format("getName(0): %s%n", path.getName(0));
            System.out.format("getNameCount: %d%n", path.getNameCount());
            System.out.format("subpath(0,2): %d%n", path.subpath(0,2));
            System.out.format("getParent: %s%n", path.getParent());
            System.out.format("getRoot: %s%n", path.getRoot());
            System.out.format("isHidden: %s%n", path.isHidden());

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


上面的代码中我们创建Path时使用的是绝对路径,下面我们来看看创建路径时使用相对路径时,这段代码的执行结果:
            //Path path = Paths.get("sally/bar");     // Solaris syntax
            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方法,例如:
                  Path p1 = Paths.get("/home/logfile");
                  System.out.format("%s%n", p1.toUri());  // 结果是 file:///home/logfile

      注意在这里即使/home/logfile'指向的目录或文件不存在,这段代码同样能够执行成功。
    * toAbsolutePath方法
      该方法将路径转换为绝对路径。如果原来的Path已经是绝对路径,该方法直接返回原有的Path对象。
      我们来看看下面的例子:
                          Path path = Paths.get("home\\joe\\foo");
                          Path absolutePath = path.toAbsolutePath();
                          System.out.println(path == absolutePath); //结果是false
                         
                          Path path2 = Paths.get("c:\\home\\joe\\foo ");
                          Path absolutePath2 = path2.toAbsolutePath();
                          System.out.println(path2 == absolutePath2);//结果是true

      同样的,toAbsolutePath方法并不需要Path所指向的文件或目录存在。
    * toRealPath方法
      这个方法会返回一个已经存在的文件或目录的真实路径(如果文件或目录不存在或无法访问,该方法会抛出异常)。该方法会执行以下的操作:
      如果传入的参数是true并且文件系统支持符号链接,则解析路径中存在的符号链接(如果有的话)。
      如果原来的Path是相对路径,将其转换成绝对路径。
      如果路径中含有冗余信息,返回的Path中这些冗余信息会被去除。


连接两个Path
可以使用resolve方法来将两个Path连接起来。该方法的参数是一个字符串。如果该字符串代表的是一个相对路径,那么这个路径会被扩展到原来的路径后。如果传入的字符串是一个绝对路径,那么返回的值就是传入的这个绝对路径。例如:
            Path p1 = Paths.get("C:\\home\\joe\\foo");   
            System.out.format("%s%n", p1.resolve("bar")); // 结果是 C:\home\joe\foo\bar

            Paths.get("foo").resolve("c:\\home\joe");       // 结果是  C:\home\joe

创建两个路径之间的路径
这个功能说起来有些绕口,实际的功能就是创建两个指定的目录或文件之间的相对路径。例如:
            Path p1 = Paths.get("joe/foo");
            Path p2 = Paths.get("sally");

在这个例子中,由于两个路径都是相对路径,没有其他的信息,我们会认为这两个joe和sally是同一级的兄弟目录,因此有以下的结果
            Path p1_to_p2 = p1.relativize(p2);   // 结果是 ../../sally
            Path p2_to_p1 = p2.relativize(p1);   // 结果是 ../joe/foo

让我们看看另外一个例子:
            Path p1 = Paths.get("home");
            Path p3 = Paths.get("home/sally/bar");
            Path p1_to_p3 = p1.relativize(p3);  // 结果是 sally/bar
            Path p3_to_p1 = p3.relativize(p1);  // 结果是 ../..

在这个例子中,两个路径共享同一个节点-home,所以结果并不是../home/sally/bar和../../../home.
如果两个路径中有一个是绝对路径,另外一个是相对路径,relative方法会抛出异常。如果两个路径都是绝对路径,那么relative方法的行为和系统相关,不同的系统可能不同。
我在Windows操作系统下实验了一下,如果两个路径属于同一个硬盘,那么可以执行成功,否则会抛出异常。
    Path path1 = Paths.get("c:\\abcd\\efg");
    Path path2 = Paths.get("c:\\temp");
    System.out.println(path1.relativize(path2));        //结果是..\..\temp
    System.out.println(path2.relativize(path1));        //结果是..\abcd\efg

    Path path3 = Paths.get("c:\\abcd\\efg");
    Path path4 = Paths.get("d:\\temp");
    System.out.println(path3.relativize(path4));        //抛出异常

Path的比较
Path提供equals方法来检查两个Path是否相等。但是这里要注意的是比较的并不是两个Path是否指向同一个目录或者文件。请看下面的例子:
    Path path1 = Paths.get("abcd\\123");
    Path path2 = Paths.get("abcd\\123");
    Path path3 = Paths.get("abcd\\.\\123");
    System.out.println(path1.equals(path2));        //true
    System.out.println(path1.equals(path3));        //false
    System.out.println(path1.equals(path3.normalize())); //true
    System.out.println(path1.equals(path1.toAbsolutePath()));        //false

Path类还提供了startsWith和endsWith方法,这两个方法用来检查路径是否以指定的字符串开始或者结束,例如:
            Path path = ...;
            Path otherPath = ...;
            Path beginning = Paths.get("/home");
            Path ending = Paths.get("foo");

            if (path.equals(otherPath)) {
                //equality logic here
            } else if (path.startsWith(beginning)) {
                //path begins with "/home"
            } else if (path.endsWith(ending)) {
                //path ends with "foo"
            }

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

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,说明无法验证该文件是否存在。



转载自  开发者的天空
分享到:
评论

相关推荐

    Java JDK 7学习笔记(国内第一本Java 7,前期版本累计销量5万册)

     《Java JDK 7学习笔记》将IDE操作纳为教学内容之一,使读者能与实践结合,提供的视频教学能更清楚地帮助读者掌握操作步骤。 内容简介 书籍 计算机书籍  《java jdk 7学习笔记》是作者多年来教学实践经验的总结...

    java jdk8 学习笔记

    C:\lib\abc.jar 指定jvm寻找.class文件路径的方法有三种,分别是从当前目录下寻找、某个文件夹下寻找或在链接库的jar文件中寻找。 同样,使用命令行指定classpath的方式优先于从系统读取classpath环境变量。 7...

    java02——Java概述

    答:编译的动作其实就是翻译,把操作系统看不懂的内容变成操作系统能看懂的内容->产生新的class文件(字节码文件) 3)①Java SE: Java 语言的标准版,用于桌面应用的开发,是其他两个版本的基础; ②Java ME:...

    3Java SE(下).doc

    1)表示当前项目根目录下的文件test.txt,在描述文件或目录时,我们指定的路径最好,使 用相对路径,否则会出现系统差异,不利于跨平台。 2)".":当前目录,在eclipse中运行时,表示当前项目的根目录 3)java.io....

    JAVA_API1.6文档(中文)

    java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务...

    Java 1.6 API 中文 New

    java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务...

    java api最新7.0

    java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务...

    java本科毕业设计_从业人员在线培训系统源代码.zip

    修改相关路径,配置正确的图片路径、文件路径、附件路径、Mapper扫描路径。 修改所有application.properties文件中的Nacos服务,使用自己的Nacos服务地址和端口 修改所有application.properties文件中的Redis服务,...

    java jdk-api-1.6 中文 chmd

    Java SE Platform 软件包 java.applet 提供创建 applet 所必需的类和 applet 用来与其 applet 上下文通信的类。 java.awt 包含用于创建用户界面和绘制图形图像的所有类。 java.awt.color 提供用于颜色空间的类。 ...

    JavaAPI1.6中文chm文档 part1

    java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务...

    java自动发邮件

    java自动发邮件不错哦,美女程序猿web.xml文件 <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <servlet-name>...

    JAVA--达内培训笔记

    1、Java之父Golsling 1995年5月23日 Java诞生 1998年12月 1.2版本 Java2 J2SE J2EE J2ME 2004年12月 1.5版本(5.0) Java JavaSE JavaEE JavaME 2、Java SE --- Java标准平台 Java EE --- 企业级平台 Java ...

    JavaAPI中文chm文档 part2

    java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务...

    浏览器插件

    7、 当使用java命令解释一个程序时,一定需要 classpath 环境属性来定位类资源路径; 2、选择题 1、 下面那个是属于解释Java程序所使用到命令?(A) A、 java.exe B、 javac.exe C、 keytool.exe D、 cmd.exe 2、 ...

    java小型用户管理系统

    本系统用java开发,数据库为mysql。数据库文件已打包,行解压后存放至mysql安装对应路径下即可运行。 比较基础的代码,适合初学java者。

    [Java参考文档]

    java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务...

    [Java参考文档].JDK_API 1.6

    java.nio.channels 定义了各种通道,这些通道表示到能够执行 I/O 操作的实体(如文件和套接字)的连接;定义了用于多路复用的、非阻塞 I/O 操作的选择器。 java.nio.channels.spi 用于 java.nio.channels 包的服务...

Global site tag (gtag.js) - Google Analytics