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

  -----------------------------------------------------------------------------------------------------------------------------

  完。

  

时间: 2024-11-10 17:00:45

Java 7 中 NIO.2 的使用——第一节 Path 类的使用的相关文章

Java 7 中 NIO.2 的使用——第二节 元数据文件的属性

如果你有很多疑问关于一个文件或目录,它是否是隐藏的,它的大小是多少,谁拥有它,你可以从元数据中得到这些信息.所谓的元数据,就是描述数据的数据. NIO.2组织了这些原数据的属性的概念,并提供了java.nio.file.attribute 包去访问它们.因为不同的文件系统有不同的概念跟踪这些属性,所以,NIO.2根据特定的文件系统进行映射然后对应到不同的view中.通常情况下,view会提供一些通用的方法,例如readAttributes().除此而外,你可以通过getAttribute() 和

Java 7 中 NIO.2 的使用——第四节 文件和目录

Files类提供了很多方法用于检查在于你真正实际去操作一个文件或目录.这些方法强烈推荐,也非常有用,也能避免很多异常的发生.例如,一个很好的习惯就是在你试着移动一个文件从一个地方到另一个地方的时候,先检查文件是否存在. 检查一个文件或目录是否存在 在前面的例子中已经演示到,Path实例能够有效的映射到一个文件或是目录甚至这个文件或目录物理上根本不存在.再是,Path的很多方法不会实际操作文件本身就能成功地应用.所以,事先判断一个目录或是文件存在就显得非常重要.下面有两个方法用来判断文件是否存在.

《MonkeyRunner原理剖析》第九章-MonkeyImage实现原理 - 第一节 - 关键类作用及关系

作者 自主博客 微信 CSDN 天地会珠海分舵 http://techgogogo.com 服务号:TechGoGoGo 扫描码: http://blog.csdn.net/zhubaitian

在Java 8中如何处理日期和时间

常有人问我学习一个新库的最好方式是什么?我的答案是在实际项目中使用它.项目中有很多真正的需求驱使开发者去发掘并学习新库.简单得说就是任务驱动学习探 索.这对Java 8新日期时间API也不例外.我创建了20个基于任务的实例来学习Java 8的新特性.从最简单创建当天的日期开始,然后创建时间及时区,接着模拟一个日期提醒应用中的任务--计算重要日期的到期天数,例如生日.纪念日.账单 日.保费到期日.信用卡过期日等.示例 1.在Java 8中获取今天的日期Java 8 中的 LocalDate 用于表

20 个案例教你在 Java 8 中如何处理日期和时间?

前言 前面一篇文章写了<SimpleDateFormat 如何安全的使用?>, 里面介绍了 SimpleDateFormat 如何处理日期/时间,以及如何保证线程安全,及其介绍了在 Java 8 中的处理时间/日期默认就线程安全的 DateTimeFormatter 类.那么 Java 8 中该怎么样处理生活中常见的一些日期/时间呢?比如:计算一周后的日期:计算一年前或一年后的日期:检查闰年等. 接下来创建了 20 个基于任务的实例来学习 Java 8 的新特性.从最简单创建当天的日期开始,然

在 Java 8 中获取日期

前言 前面一篇文章写了<SimpleDateFormat 如何安全的使用?>, 里面介绍了 SimpleDateFormat 如何处理日期/时间,以及如何保证线程安全,及其介绍了在 Java 8 中的处理时间/日期默认就线程安全的 DateTimeFormatter 类.那么 Java 8 中该怎么样处理生活中常见的一些日期/时间呢?比如:计算一周后的日期:计算一年前或一年后的日期:检查闰年等. 接下来创建了 20 个基于任务的实例来学习 Java 8 的新特性.从最简单创建当天的日期开始,然

灵魂拷问:如何检查Java数组中是否包含某个值 ?

摘自:https://www.cnblogs.com/qing-gee/p/12053156.html 在逛 programcreek 的时候,我发现了一些专注细节但价值连城的主题.比如说:如何检查Java数组中是否包含某个值 ?像这类灵魂拷问的主题,非常值得深入地研究一下. 另外,我想要告诉大家的是,作为程序员,我们千万不要轻视这些基础的知识点.因为基础的知识点是各种上层技术共同的基础,只有彻底地掌握了这些基础知识点,才能更好地理解程序的运行原理,做出更优化的产品. 我曾在某个技术论坛上分享过

Java的中BIO、NIO、AIO-2

Java的中BIO.NIO.AIO-2 java 举个栗子 接上一篇接着说,C/S模式.Reactor模式.Proactor模式是服务器处理IO常用的处理模型,这一篇就来解释一下这几种模式: 以一个餐饮为例,每一个人来就餐就是一个事件,他会先看一下菜单,然后点餐.就像一个网站会有很多的请求,要求服务器做一些事情.处理这些就餐事件的就需要我们的服务人员了. 在多线程处理的方式会是这样的: 一个人来就餐,一个服务员去服务,然后客人会看菜单,点菜. 服务员将菜单给后厨. 二个人来就餐,二个服务员去服务

Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO https://blog.csdn.net/column/details/21963.html 部分代码会放在我的的Github:https://github.com/h2pl/ 浅谈 Linux