Java 7 中 NIO.2 的使用——第一节 Path 类的使用
路径隶属于文件系统,实际上它是存储和组织媒体文件的格式,通常在一块或多块硬盘设备上,以便于非常容易地检索。文件系统可以通过 java.nio.file.FileSystems 这个final 类来访问,通常我们用来获取它的实例然后做我们想做的事情。FileSystems 包含下面两个非常重要的方法,还有 newFileSystem() 方法,用来构建一个新的文件系统实例。
- getDefault(): 这个静态方法会返回一个默认的FileSystem 给 JVM——通常是操作系统默认的文件系统。
- getFileSystem(URI uri): 这个静态方法根据提供的可以匹配 URI 模式的一系列可用的文件系统提供者中返回一个文件系统。Path类可以操作任何类型的文件系统并可以使用任何存储的地方(java.nio.file.FileStore这个类会呈现潜在的存储)。通常情况下,Path类指向默认的操作系统的文件,但是在 NIO.2 中 彻底模块化了—— 可以是内存中数据,在互联网上,在虚拟文件系统的FileSystem 类的实现,这些都可以都可以完美的被NIO.2接受,NIO.2 提供了所有文件系统的功能,我们需要执行在文件,目录或是一个link 链接文件上。
Path类实际上是java.io.File类的升级版本,但是File类有一些特定的操作,所以File类不要被认为是过时的类,也不要把他当作一个障碍。此外,在Java 7 中,这两个类都是可以继续使用,这就意味着可以混合使用这两个类来获取最佳的 API 操作。 Java 7 中提供了非常简单的API 方便这两者的互相转换。
在以前IO操作都是这样写的。
import java.io.File;
…
File file = new File("index.html");
但在Java7 中,我们可以这样写:
import java.nio.file.Path;
import java.nio.file.Paths;
…
Path path = Paths.get("index.html");
最后总结,一个 Path 类 是一个路径在文件系统中的程序表示。Path基本上就是一个文件路径的字符串,实际的引用的资源可以不存在。
一旦你确定了文件系统和文件或是目录的存储的地方,你就可以创建一个Path实例。绝对路径,相对路径,使用“.”定义的当前路径以及“..” 定义的父级路径,路径中包含一个文件或是目录名字,这些都可以用Path类来搞定。最简单办法是使用Paths帮助类来调用get() 方法。下面的例子演示了使用同一路径定义path的几种不同的方法。默认使用C:\rafaelnadal\tournaments\2009\BNP.txt这个路径。
定义一个绝对目录
一个绝对目录就是包含了根目录然后接下来几层子目录最后是文件名或是最后一层的目录。你可以使用下面代码来定义一个绝对目录Path类。
Path path = Paths.get("C:/rafaelnadal/tournaments/2009/BNP.txt");
get()方法也支持把路径分割成一块一块的。NIO会重新组织路径。看下面代码:
Path path = Paths.get("C:/rafaelnadal/tournaments/2009", "BNP.txt");
Path path = Paths.get("C:", "rafaelnadal/tournaments/2009", "BNP.txt");
Path path = Paths.get("C:", "rafaelnadal", "tournaments", "2009", "BNP.txt");
定义一个相对于根路径的相对路径
相对路径是全路径的一部分,相对路径通常用在创建web 页面中。相对路径要比绝对路径用的更加广泛。在当前路径下保存一个相对路径通常要加上文件分隔符。例如,如果当前路径是C盘,则绝对路径应该是:C:\rafaelnadal\tournaments\2009\BNP.txt
:
Path path = Paths.get("/rafaelnadal/tournaments/2009/BNP.txt");
Path path = Paths.get("/rafaelnadal","tournaments/2009/BNP.txt");
定义一个相对于工作目录的相对路径
当你定义一个相对于当前工作目录的路径,这个路径就不用使用文件分隔符作为开始。例如向前目录是相对于根目录C盘下的/ATP目录,则根据下面的代码返回绝对路径是:C:\ATP\rafaelnadal\tournaments\2009\BNP.txt
:
Path path = Paths.get("rafaelnadal/tournaments/2009/BNP.txt");
Path path = Paths.get("rafaelnadal","tournaments/2009/BNP.txt");
定义一个从URI获取的路径
在一些情况下,你需要从URI中创建一个路径,你可以使用URI.create() 方法根据指定的字符串从URI中创建路径。
import java.net.URI;
…
Path path = Paths.get(URI.create("file:///rafaelnadal/tournaments/2009/BNP.txt"));
Path path = Paths.get(URI.create("file:///C:/rafaelnadal/tournaments/2009/BNP.txt"));
你也可以使用FileSystems.getDefault().getPath() 方法来定义一个Path类。
import java.nio.file.FileSystems;
…
Path path = FileSystems.getDefault().getPath("/rafaelnadal/tournaments/2009", "BNP.txt");
Path path = FileSystems.getDefault().getPath("/rafaelnadal/tournaments/2009/BNP.txt");
Path path = FileSystems.getDefault().getPath("rafaelnadal/tournaments/2009", "BNP.txt");
Path path = FileSystems.getDefault().
getPath("/rafaelnadal/tournaments/./2009","BNP.txt").normalize();
获取系统的主目录的路径
当你想获取主目录的路径时,可以使用下面的代码:
Path path = Paths.get(System.getProperty("user.home"), "downloads", "game.exe");
在Windows 7 中,返回的路径是C:\Users\{your user name}\downloads\game.exe,在Linux系统中,则返回
/home/{your user name}/downloads/game.exe。
----------------------------------------------------------------------------------------------------------------------------
获取路径的信息
当你定义完Path对象后,接下来会有一系列的方法用来访问文件的信息。首先定义一个Path实例:
Path path = Paths.get("C:", "rafaelnadal/tournaments/2009", "BNP.txt");
获取文件或目录的名字:
//output: BNP.txt
System.out.println("The file/directory indicated by path: " + path.getFileName());
获取根目录
//output: C:\
System.out.println("Root of this path: " + path.getRoot());
获取路径的父目录
//output: C:\rafaelnadal\tournaments\2009
System.out.println("Parent: " + path.getParent());
获取路径名的元素
你可以使用 getNameCount()方法获取路径层级的个数,然后再使用getName()循环遍历每个元素的名字。
//output: 4
System.out.println("Number of name elements in path: " + path.getNameCount()); //output: rafaelnadal tournaments 2009 BNP.txt
for (int i = 0; i < path.getNameCount(); i++) {
System.out.println("Name element " + i + " is: " + path.getName(i));
}
获取子路径
//output: rafaelnadal\tournaments\2009
System.out.println("Subpath (0,3): " + path.subpath(0, 3));
--------------------------------------------------------------------------------------------------------------------------
Path的转换
在这节中,将会介绍怎样由一个Path对象转换成字符串,URI,绝对路径,相对路径以及File对象。
先定义一个Path实例:
Path path = Paths.get("/rafaelnadal/tournaments/2009", "BNP.txt");
转化成一个字符串
//output: \rafaelnadal\tournaments\2009\BNP.txt
String path_to_string = path.toString();
System.out.println("Path to String: " + path_to_string);
转换成一个URI
//output: file:///C:/rafaelnadal/tournaments/2009/BNP.txt
URI path_to_uri = path.toUri();
System.out.println("Path to URI: " + path_to_uri);
由相对路径转换成绝对路径
//output: C:\rafaelnadal\tournaments\2009\BNP.txt
Path path_to_absolute_path = path.toAbsolutePath();
System.out.println("Path to absolute path: " + path_to_absolute_path.toString());
转换成真实路径
import java.io.IOException;
…
//output: C:\rafaelnadal\tournaments\2009\BNP.txt
try {
Path real_path = path.toRealPath(LinkOption.NOFOLLOW_LINKS);
System.out.println("Path to real path: " + real_path);
} catch (NoSuchFileException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
转换成File对象
//output: BNP.txt
File path_to_file = path.toFile(); //output: \rafaelnadal\tournaments\2009\BNP.txt
Path file_to_path = path_to_file.toPath();
System.out.println("Path to file name: " + path_to_file.getName());
System.out.println("File to path: " + file_to_path.toString());
--------------------------------------------------------------------------------------------------------------------------
合并两个路径
合并两个路径的技术允许你先定义一个固定的根目录然后再附上局部的路径,在NIO.2 中,使用resolve() 方法来实现这一功能。
//define the fixed path
Path base = Paths.get("C:/rafaelnadal/tournaments/2009"); //resolve BNP.txt file
Path path_1 = base.resolve("BNP.txt");
//output: C:\rafaelnadal\tournaments\2009\BNP.txt
System.out.println(path_1.toString()); //resolve AEGON.txt file
Path path_2 = base.resolve("AEGON.txt");
//output: C:\rafaelnadal\tournaments\2009\AEGON.txt
System.out.println(path_2.toString());
还有一个方法用于兄弟路径,叫resolveSibling(),它会根据给定的路径去替换当前的路径。
//define the fixed path
Path base = Paths.get("C:/rafaelnadal/tournaments/2009/BNP.txt"); //resolve sibling AEGON.txt file
Path path = base.resolveSibling("AEGON.txt");
//output: C:\rafaelnadal\tournaments\2009\AEGON.txt
System.out.println(path.toString());
--------------------------------------------------------------------------------------------------------------------------------
在两个位置中构造一个路径
当你需要构造从一个位置到另一个位置的路径的时候,你可以使用relativize()方法。直接上代码。
Path path01 = Paths.get("BNP.txt");
Path path02 = Paths.get("AEGON.txt");
在这种情况下,可以假设这两个txt文件在同一层目录下,这就意味着你你可以从一个文件导航到另一个文件根据目录的层级。
//output: ..\AEGON.txt
Path path01_to_path02 = path01.relativize(path02);
System.out.println(path01_to_path02); //output: ..\BNP.txt
Path path02_to_path01 = path02.relativize(path01);
System.out.println(path02_to_path01);
另一种情况是两个文件不在同一层的目录中,考虑下面的这个情况:
Path path01 = Paths.get("/tournaments/2009/BNP.txt");
Path path02 = Paths.get("/tournaments/2011");
这两个路径都有一个共同的根元素:/tournaments, 从path01 导航到 path02,你需要向上两个目录层级然后再向下一个层级(
..\..\2011
)。从path02导航到path01,你需要向上一个层级然后向下两个层级,relativize()方法就是这样做的。
//output: ..\..\2011
Path path01_to_path02 = path01.relativize(path02);
System.out.println(path01_to_path02); //output: ..\2009\BNP.txt
Path path02_to_path01 = path02.relativize(path01);
System.out.println(path02_to_path01);
注意,如果只有一个path包含根元素,那么相对路径是不能构造的,必保证两个path包含根元素。即使这样,相对路径的构造是依赖于系统的。
-----------------------------------------------------------------------------------------------------------------------------------
比较两个路径
两个路径是否相等可以通过不同的方式和目的去测试。你可以使用 Path.equals()方法,这个方法并不直接访问文件系统,所以没有强制要求文件必须存在,
也不会检查两个文件是否是同一个文件。在有的系统中,路径的比较会忽略大小写,有的则是大小写敏感的。下面的代码中表示的是同一个文件,但是并不相等。
Path path01 = Paths.get("/rafaelnadal/tournaments/2009/BNP.txt");
Path path02 = Paths.get("C:/rafaelnadal/tournaments/2009/BNP.txt"); if(path01.equals(path02)){
System.out.println("The paths are equal!");
} else {
System.out.println("The paths are not equal!"); //true
}
有时候你想检查两个路径是否是同一个目录和文件,你可以很容易地使用java.nio.File.Files.isSameFile()方法,要注意,要保证路径是真实存在。
try {
boolean check = Files.isSameFile(path01, path02);
if(check){
System.out.println("The paths locate the same file!"); //true
} else {
System.out.println("The paths does not locate the same file!");
}
} catch (IOException e) {
System.out.println(e.getMessage());
}
因为Path实现了Comparable接口,所以你可以使用
compareTo()方法对路径进行比较,根据字典顺序进行比较。
//output: 24
int compare = path01.compareTo(path02);
System.out.println(compare);
还可以进行局部路径的比较。
boolean sw = path01.startsWith("/rafaelnadal/tournaments");
boolean ew = path01.endsWith("BNP.txt");
System.out.println(sw); //output: true
System.out.println(ew); //output: true
------------------------------------------------------------------------------------------------------------------------------
遍历路径元素的名称
因为Path实现了Iterable接口,所以你可以得到一个对象然后新型循环遍历一个路径的信息。请看下面的代码。
Path path = Paths.get("C:", "rafaelnadal/tournaments/2009", "BNP.txt"); for (Path name : path) {
System.out.println(name);
}
输出结构如下所示:
rafaelnadal
tournaments
2009
BNP.txt
-----------------------------------------------------------------------------------------------------------------------------
完。
Java 7 中 NIO.2 的使用——第一节 Path 类的使用的更多相关文章
- Java 7 中 NIO.2 的使用——第二节 元数据文件的属性
如果你有很多疑问关于一个文件或目录,它是否是隐藏的,它的大小是多少,谁拥有它,你可以从元数据中得到这些信息.所谓的元数据,就是描述数据的数据. NIO.2组织了这些原数据的属性的概念,并提供了java ...
- Java 7 中 NIO.2 的使用——文件递归操作
众所周知,递归编程是一项有争议的技术,因为它需要大量的内存,但是它能简化一些编程任务.基本上,一个递归操作都是程序调用自己传递参数修改的值或者参数传递到当前的程序循环中.递归编程通常用来计算阶乘斐波那 ...
- Java 7 中 NIO.2 的使用——第四节 文件和目录
Files类提供了很多方法用于检查在于你真正实际去操作一个文件或目录.这些方法强烈推荐,也非常有用,也能避免很多异常的发生.例如,一个很好的习惯就是在你试着移动一个文件从一个地方到另一个地方的时候,先 ...
- Java文件中为什么只能有一个public修饰的类, 并且类名还必须与文件名相同
当编写一个java源代码文件时,此文件通常被称为编译单元(有时也被称为转译单元).每个编译单元都必须有一个后缀名.java,而在编译单元内则可以有一个public类,该类的名称必须与文件的名称相同(包 ...
- 对Java配置文件中敏感信息进行加解密的工具类
在 JavaEE 配置文件中,例如 XML 或者 properties 文件,由于某些敏感信息不希望普通人员看见,则可以采用加密的方式存储,程序读取后进行解密. 常见的如: 数据库用户密码,短信平台用 ...
- java程序中访问https时,报 PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
在java中使用https访问数据时报异常: Caused by: sun.security.validator.ValidatorException: PKIX path building fail ...
- 《MonkeyRunner原理剖析》第九章-MonkeyImage实现原理 - 第一节 - 关键类作用及关系
MonkeyRunner框架暴露了几个类的大量的API出去给用户编写脚本时候使用,其中最主要的三个就是: MonkeyDevice目标设备操作类,HierarchyViewer窗口界面对象操作类以及M ...
- 在 Java 8 中获取日期
前言 前面一篇文章写了<SimpleDateFormat 如何安全的使用?>, 里面介绍了 SimpleDateFormat 如何处理日期/时间,以及如何保证线程安全,及其介绍了在 Jav ...
- 20 个案例教你在 Java 8 中如何处理日期和时间?
前言 前面一篇文章写了<SimpleDateFormat 如何安全的使用?>, 里面介绍了 SimpleDateFormat 如何处理日期/时间,以及如何保证线程安全,及其介绍了在 Jav ...
随机推荐
- Linux动态库的查找路径
前两天写了一个动态库,然后试图编译到程序里面去运行,结果发现编译的时候通过gcc的-L参数来指定路径仅仅能让编译通过,运行时还是会出问题的. 比如下面这个例子: main.c是主程序,sum.c中间含 ...
- HOOK API 在多线程时应该注意的问题点
在使用INLINE HOOK API实现对系统API的拦截时,正常情况下并没有太大问题,但一旦涉及到多线程,不管是修改IAT还是JMP,2种方法均会出现不可预料的问题,特别是在HOOK一些复杂的大型系 ...
- Java 为什么使用抽象类和接口
Java接口和Java抽象类代表的就是抽象类型,就是我们需要提出的抽象层的具体表现.OOP面向对象的编程,如果要提高程序的复用率,增加程序的可维护性,可扩展性,就必须是面向接口的编程,面向抽象的编程, ...
- asp.net 发布后用IP访问正常,用机器名访问布局出错
问题如题[发布后IP访问正常,用机器名访问布局出现问题] 出现此问题的原因:IE文档模型发生变化,比如ip访问时IE文档模型为:IE10,换用机器名访问时,文档模型变为IE7 解决方法:设置默认IE版 ...
- ROS多个master消息互通
需求 有时候我们需要有几个不同的master, 他们之间要交换topic的内容,这时候就不能使用ros自带的设置同一个master的方法. 我们的处理方法是,构造一个client和一个server,他 ...
- 正确打印含unicode字符的dict
python中,dict 对象转换为类似为 \UXXXX 的格式:这种格式英文称为 code point,完全看不懂:当然,也可以通过这个网站来转换 http://rishida.net/tools/ ...
- C/C++走过的坑(基础问题篇)
1.有符号int与无符号int比较 #define TOTOL_ELEMENTS (sizeof(a) / sizeof(a[0]) ); int main() { int a[] = {23,24, ...
- Ajax-goahead局部刷新页面
软件开发最常用的方法是:C/S,B/S.如果嵌入式设备中使用Ajax,那么既可以使用C/S方式,也可以使用B/S开发上位机.最近公司的一个项目需要异步获取后台数据,使用form更新数据时会有空白卡顿不 ...
- Express实现http和https服务
一.介绍Http与Https 概念 HTTP: 超文本传输协议(Hypertext transfer protocol) 是一种详细规定了浏览器和万维网服务器之间互相通信的规则,通过因特网传送万维网文 ...
- .Net码农学Android---快速了解数据存储
数据存储 Andoid中的数据存储和我们平时见到的不一样,或者说移动设备的存储和平时不一样.Andoid中的存储方式有五种, 单把存储拎出来,是因为我们后续的开发会经常用到,重要性不言而喻,多样的存储 ...