使用Path接口在文件和目录路径上操作。
使用Files类检查、读取、删除、复制、移动、管理文件或目录的元数据。

NIO.2

image.png

  • Java 的第一个版本中java.io包的File类缺乏对File文件属性的支持
  • java1.4在 java.nio 包中引入了NIO(非阻塞输入/输出) API,实现了通道、缓冲和新的字符集等新功能(这个API 并没有完全解决 Java.io包的问题)
  • 在 java7中,NIO.2 API 被添加到了 java.nio.file 包中(实际上,由于这是一个新包,NIO.2并不是NIO API的更新,而且它们关注的是不同的东西)

NIO.2包的作用

  • NIO. 2为访问文件和文件系统、符号链接、互操作性和异常等提供了更好的支持。
  • File、 Path、 Paths 和 Files 的主要类旨在提供一种处理文件的更简单方法,并作为 java.io 的替代品。文件类。

关于Path和Paths

  • Path是用于处理路径的方法的接口
  • Paths是具有创建 Path 对象的静态方法的工具类
    其只有2种静态方法获得Path,一个是通过String对象,一个是通过URI
    image.png

Path接口

Path 接口定义了一个对象,它表示文件或目录的路径。
考虑到路径在不同文件系统之间变化,Path使得Java 可以透明地处理不同平台之间的不同实现

  • 例如Win和Unix区别
    1.基于Windows的系统不区分大小写,而基于Unix的系统区分大小写。
    2.在基于Windows的系统中,路径由反斜杠分隔。在基于Unix的系统中,使用正斜杠。
    3.在基于Windows的系统中,根路径是驱动器号(通常是c:\)。在基于Unix的系统中,它是一个正斜杠(/)。
    4.在基于Windows的系统中,绝对路径以驱动器号开头(如c:\temp\file.txt)。在基于Unix的系统中,它以正斜杠开始(如/temp/file.txt)。
    image

获得Path接口的实现类实例

通过Paths工具类获得Path

java.nio.file.Paths类提供了两个方法来创建 Path 对象

static Path get(String first, String... more)
static Path get(URI uri)

image.png

  • Paths.get(String first, String... more)创建Path
// With an absolute path in windows
Path pathWin = Paths.get("c:\\temp\\file.txt");
// With an absolute path in unix
Path pathUnix = Paths.get("/temp/file.txt");
// With a relative path
Path pathRelative = Paths.get("file.txt");
//Using the varargs parameter
// (the separator is inserted automatically)
Path pathByParts = Paths.get("c:", "temp", "file.txt");
  • Paths.get(URI uri)创建Path
    必须使用一个 java.net.uri 实例。因为我们使用的是文件,所以 URI 模式必须是 file://:
try {
    Path fileURI = Paths.get(new URI("file:///c:/temp/file.txt"));
} catch (URISyntaxException e) {
    //This checked exception is thrown by the URI constructor
}

如果不想捕获 URISyntaxException,可以使用静态方法 URI.create (String)。它用 IllegalArgumentException (RuntimeException的子类)包装 URISyntaxException(Exception的子类) 异常
image.png
注意三个斜杠。file:///表示绝对路径(file://模式加上根目录的另一个/)。我们可以借助toAbsolutionPath()方法来测试这一点,该方法返回路径对象的绝对路径表示:

Path fileURI = Paths.get(URI.create("file:///file.txt"));
System.out.println(fileURI.toAbsolutePath());
C:\file.txt // in Windows-based systems
/file.txt // Or in Unix-based systems
  • Mac中
    image.png
    image.png
  • Win中
    image.png
    image.png
    其JDK的源码都不一样,Path接口的实现不同

通过File类创建Path

File file = new File("/file.txt");
Path path = file.toPath();

Path路径组成

Path 对象的绝对路径表示有一个根组件(c: 或/)和一系列名称,名称由一个(向前或向后)斜杠分隔。
这些名称表示导航到目标文件或目录所需的目录。序列中的最后一个名称表示目标文件或目录的名称。

  • 例如c:\temp\dir1\file.txt (或者它的等效 Unix/temp/dir1/file.txt)
    Root: c:\ (or /)
    Name 1: temp
    Name 2: dir1
    Name 3: file.txt

Path 对象有一些方法来获取这些信息。除了 toString ()和 getNameCount () ,这些方法都返回一个 Path 对象

Path path = Paths.get("C:\\temp\\dir1\\file.txt");
// Or Path path = Paths.get("/temp/dir1/file.txt");
System.out.println("toString(): " + path.toString());
System.out.println("getFileName(): " + path.getFileName());
System.out.println("getNameCount(): " +path.getNameCount());
// Indexes start from zero 
System.out.println("getName(0): " + path.getName(0));
System.out.println("getName(1): " + path.getName(1));
System.out.println("getName(2): " + path.getName(2));
// subpath(beginIndex, endIndex) from beginIndex to endIndex-1
System.out.println("subpath(0,2): " + path.subpath(0,2));
System.out.println("getParent(): " + path.getParent());
System.out.println("getRoot(): " + path.getRoot());

向 getName ()和 subpath ()传递无效索引将引发 IllegalArgumentException (RuntimeException)
其输出结果应为

toString(): C:\temp\dir1\file.txt // Or /temp/dir1/file.txt
getFileName(): file.txt
getNameCount(): 3
getName(0): temp
getName(1): dir1
getName(2): file.txt
subpath(0,2): temp\dir1 // Or temp/dir1
getParent(): C:\temp\dir1 // Or /temp/dir1
getRoot(): C:\ // Or /
  • 如果路径被指定为相对路径(并且假设这段代码是在 c: temp 目录中执行的) :
Path path = Paths.get("dir1\\file.txt");// Or dir1/file.txt 
System.out.println("toString(): " + path.toString());
System.out.println("getFileName(): " + path.getFileName());
System.out.println("getNameCount(): " + path.getNameCount());
System.out.println("getName(0): " + path.getName(0));
System.out.println("getName(1): " + path.getName(1));
System.out.println("subpath(0,2): " + path.subpath(0,2));
System.out.println("getParent(): " + path.getParent());
System.out.println("getRoot(): " + path.getRoot());

结果为

toString(): dir1\file.txt // Or dir1/file.txt
getFileName(): file.txt
getNameCount(): 2
getName(0): dir1
getName(1): file.txt
subpath(0,2): dir1\file.txt // Or dir1/file.txt
getParent(): dir1
getRoot(): null
  • 当使用路径时,可以使用:
    ./引用当前目录
    ../引用父级目录
    可以使用 normalize ()方法来消除冗余,使得路径现实正常化
    image.png
Path path = Paths.get("/temp/dir1/../file.txt");
System.out.println(path); // /temp/dir1/../file.txt
Path path2 = path.normalize();
System.out.println(path2); // /temp/file.txt

image.png

  • normalize()弊端
    此方法不访问文件系统以知道是否存在文件,因此删除。.以及路径的前面名称可能导致路径不再引用原始文件。当前一个名称是一个符号链接(对另一个文件的引用)时,就会发生这种情况

toRealPath()方法

//返回现有文件的真实路径。
Path toRealPath(LinkOption... options) throws IOException

image.png

  • 相比较normalize()的好处
    1.默认情况下如果以LinkOption.NOFOLLOW_LINKS作为参数传递,则符号链接后面不跟(默认情况下是这样)。
    2.如果路径是相对的,则返回绝对路径。
    3.它返回一个删除了冗余元素(如果有的话)的路径。

Files类

注意点:

  • java.nio.file.Files对文件和目录进行常见操作的静态方法
    public方法全部为static
  • 不同于java.io.File类,Files方法都使用Path对象
    全部入参都使用Path
    image.png

常用方法

  • 检查一个路径是否可读(如果文件不存在或者 JVM 没有访问它的特权,那么这个路径就不可读)
static boolean isReadable(Path path)
  • 检查一个路径是否可写(如果文件不存在或者 JVM 没有访问它的特权,那么这个路径就不可写)
static boolean isWritable(Path path)
  • 检查一个文件是否存在并可执行:
static boolean isExecutable(Path path)
  • 检查两个路径是否引用同一个文件(如果一个路径表示一个符号链接,则很有用)。如果两个 Path 对象都相等,那么这个方法返回 true,而不检查文件是否存在
static boolean isSameFile(Path path,Path path2) throws IOException
  • 将整个文件加载到内存中(只对小文件有用)
static byte[] readAllBytes(Path path)
                              throws IOException
static List<String> readAllLines(Path path)
                              throws IOException
static List<String> readAllLines(Path path, Charset cs)
                              throws IOException
  • 另一种有效的方式读取文件
static BufferedReader newBufferedReader(Path path)
        throws IOException
static BufferedReader newBufferedReader(Path path, Charset cs)
        throws IOException
  • 删除文件/目录的方法
    1.删除失败(包括文件不存在)抛出异常
static void delete(Path path) throws IOException

失败时抛出异常

try {
    Files.delete(Paths.get("/temp/dir1/file.txt"));
    Files.delete(Paths.get("/temp/dir1"));
} catch (NoSuchFileException nsfe) {
    // If the file/directory doesn't exists
} catch (DirectoryNotEmptyException dnee) {
    // To delete a directory, it must be empty,
    // otherwise, this exception is thrown
} catch (IOException ioe) {
    // File permission or other problems
}

2.(不管是否删除均不会抛出异常,只会返回true、false)

static boolean deleteIfExists(Path path) throws IOException

文件被删除,这个方法返回 true; 如果文件因为不存在而无法删除,这个方法返回 false。换句话说,与第一个方法不同,这个方法不会抛出 NoSuchFileException (但是它仍然会抛出一个 DirectoryNotEmptyException 和一个 IOException,用于其他问题)

try {
    Files.deleteIfExists(Paths.get("/temp/dir1/file.txt"));
} catch (DirectoryNotEmptyException dnee) {
    // To delete a directory, it must be empty,
} catch (IOException ioe) {
    // File permission or other problems
}
  • 复制文件/目录
static Path copy(Path source, Path target,CopyOption... options) throws IOException

它返回目标文件的路径,当复制一个目录时,它的内容不会被复制

管理元数据

元数据向我们提供有关文件或目录的信息,比如它的大小、权限、创建日期等。这些信息称为属性,其中一些属性是系统相关的

Files类从Path对象获取属性

  • 文件的大小(以字节为单位)
static long size(Path path) throws IOException
  • 文件是否是目录
static boolean isDirectory(Path path, LinkOption... options)
  • 文件是否为常规文件。
static boolean isRegularFile(Path path, LinkOption... options)
  • 文件是否为符号链接
static boolean isSymbolicLink(Path path)
  • 文件是否隐藏
static boolean isHidden(Path path) throws IOException
  • 返回或更新文件上次修改的时间
static FileTime getLastModifiedTime(Path path,
            LinkOption... options) throws IOException
static Path setLastModifiedTime(Path path,
            FileTime time) throws IOException
  • 返回或更新文件的所有者
static UserPrincipal getOwner(Path path,
            LinkOption... options) throws IOException
static Path setOwner(Path path,
            UserPrincipal owner) throws IOException

//TODO

总结

  • java.nio.file的主要类是Path、Paths和Files。它们旨在替代java.io.File类。
  • Path接口定义一个表示文件或目录路径的对象。
    Path提供了创建路径对象的方法。
  • 路径对象的绝对路径表示有一个根组件(c:\或/)和一系列名称,名称之间用斜杠(正斜杠或反斜杠)隔开。
    Path接口具有获取路径元素、规范化路径和获取路径属性的方法(isAbsolute()、getFileSystem()等)。它还扩展Comparable并实现equals(),以测试相等性。
  • java.nio.file.Files类具有用于对文件和目录执行常见操作的静态方法。与java.io.File类不同,文件的所有方法都使用Path对象。

这个家伙很懒,啥也没有留下😋