Java NIO(十六) Files

简介: Java NIO Files类(java.nio.file.Files)提供了几种方法来处理文件系统中的文件。 这个Java NIO文件教程将涵盖这些方法中最常用的。

Java NIO Files类(java.nio.file.Files)提供了几种方法来处理文件系统中的文件。 这个Java NIO文件教程将涵盖这些方法中最常用的。 Files类包含许多方法,所以如果你需要一个在这里没有描述的方法,那么也检查JavaDoc。 Files类可能还有一个方法。

java.nio.file.Files类与java.nio.file.Path实例一起使用,所以在使用Files类之前,您需要了解Path类。

Files.exists()

Files.exists()方法检查给定的Path是否存在于文件系统中。

可以创建文件系统中不存在的Path实例。 例如,如果您打算创建一个新的目录,您将首先创建相应的Path实例,然后创建该目录。

由于Path实例可能指向或不指向文件系统中存在的路径,因此可以使用Files.exists()方法来确定它们是否执行(以防需要检查)。

这里是一个Java Files.exists()的例子:

Path path = Paths.get("data/logging.properties");

boolean pathExists =
        Files.exists(path,
            new LinkOption[]{ LinkOption.NOFOLLOW_LINKS});

这个例子首先创建一个Path实例,指向我们要检查的路径是否存在。 其次,该示例使用Path实例调用Files.exists()方法作为第一个参数。

注意Files.exists()方法的第二个参数。 此参数是影响Files.exists()如何确定路径是否存在的选项数组。 在上面的例子中,数组包含LinkOption.NOFOLLOW_LINKS,这意味着Files.exists()方法不应该跟随文件系统中的符号链接来确定路径是否存在。

Files.createDirectory()

Files.createDirectory()方法从Path实例创建一个新目录。 这是一个Java Files.createDirectory()示例:

Path path = Paths.get("data/subdir");

try {
    Path newDir = Files.createDirectory(path);
} catch(FileAlreadyExistsException e){
    // the directory already exists.
} catch (IOException e) {
    //something else went wrong
    e.printStackTrace();
}

第一行创建表示要创建的目录的Path实例。 在try-catch块内,调用Files.createDirectory()方法,路径为参数。 如果创建目录成功,则会返回指向新创建路径的Path实例。

如果该目录已经存在,则会抛出java.nio.file.FileAlreadyExistsException异常。 如果出现其他问题,可能会抛出IOException异常。 例如,如果所需新目录的父目录不存在,则可能会抛出IOException。 父目录是要在其中创建新目录的目录。 因此,它意味着新目录的父目录。

Files.copy()

Files.copy()方法复制一个文件到另一个从一个路径。这是一个Java NIO Files.copy()例子:

Path sourcePath      = Paths.get("data/logging.properties");
Path destinationPath = Paths.get("data/logging-copy.properties");

try {
    Files.copy(sourcePath, destinationPath);
} catch(FileAlreadyExistsException e) {
    //destination file already exists
} catch (IOException e) {
    //something else went wrong
    e.printStackTrace();
}

首先,该示例创建一个源和目标路径实例。 然后该示例调用Files.copy(),传递两个Path实例作为参数。 这将导致源路径引用的文件被复制到目标路径引用的文件。

如果目标文件已经存在,则抛出java.nio.file.FileAlreadyExistsException异常。 如果出现其他问题,则抛出IOException异常。 例如,如果复制文件的目录不存在,则抛出IOException。

覆盖现有的文件

可以强制Files.copy()覆盖现有的文件。 这里有一个例子展示如何使用Files.copy()覆盖现有的文件:

Path sourcePath      = Paths.get("data/logging.properties");
Path destinationPath = Paths.get("data/logging-copy.properties");

try {
    Files.copy(sourcePath, destinationPath,
            StandardCopyOption.REPLACE_EXISTING);
} catch(FileAlreadyExistsException e) {
    //destination file already exists
} catch (IOException e) {
    //something else went wrong
    e.printStackTrace();
}

注意第三个参数Files.copy()方法。这个参数指示复制()方法将覆盖现有的文件如果目标文件已经存在。

Files.move()

Java NIO Files类还包含将文件从一个路径移动到另一个路径的功能。 移动文件与重命名文件相同,只是移动文件可以将文件移动到不同的目录并在同一操作中更改其名称。 是的,java.io.File类也可以通过renameTo()方法来实现,但是现在在java.nio.file.Files类中也有文件移动功能。

这是一个Java Files.move()示例:

Path sourcePath      = Paths.get("data/logging-copy.properties");
Path destinationPath = Paths.get("data/subdir/logging-moved.properties");

try {
    Files.move(sourcePath, destinationPath,
            StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
    //moving file failed.
    e.printStackTrace();
}

首先创建源路径和目标路径。 源路径指向要移动的文件,目标路径指向文件应移至的位置。 然后调用Files.move()方法。 这导致文件被移动。

注意传递给Files.move()的第三个参数。 该参数告诉Files.move()方法覆盖目标路径上的任何现有文件。 这个参数实际上是可选的。

如果移动文件失败,Files.move()方法可能会引发IOException。 例如,如果文件已经存在于目标路径中,并且已经省去了StandardCopyOption.REPLACE_EXISTING选项,或者要移动的文件不存在等。

Files.delete()

Files.delete()方法可以删除文件或目录。 这里是一个Java Files.delete()的例子:

Path path = Paths.get("data/subdir/logging-moved.properties");

try {
    Files.delete(path);
} catch (IOException e) {
    //deleting file failed
    e.printStackTrace();
}

首先创建指向要删除的文件的路径。 其次调用Files.delete()方法。 如果Files.delete()由于某种原因(例如文件或目录不存在)而无法删除文件,则抛出IOException。

Files.walkFileTree()

Files.walkFileTree()方法包含递归遍历目录树的功能。 walkFileTree()方法将Path实例和FileVisitor作为参数。 Path实例指向您想要遍历的目录。 FileVisitor在转换过程中被调用。

在我解释遍历如何工作之前,首先是FileVisitor接口:

public interface FileVisitor {

    public FileVisitResult preVisitDirectory(
        Path dir, BasicFileAttributes attrs) throws IOException;

    public FileVisitResult visitFile(
        Path file, BasicFileAttributes attrs) throws IOException;

    public FileVisitResult visitFileFailed(
        Path file, IOException exc) throws IOException;

    public FileVisitResult postVisitDirectory(
        Path dir, IOException exc) throws IOException {

}

您必须自己实现FileVisitor接口,并将实现的实例传递给walkFileTree()方法。 您的FileVisitor实现的每个方法将在目录遍历期间的不同时间被调用。 如果您不需要挂接所有这些方法,则可以扩展SimpleFileVisitor类,该类包含FileVisitor接口中所有方法的默认实现。

这里是一个walkFileTree()的例子:

Files.walkFileTree(path, new FileVisitor<Path>() {
  @Override
  public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
    System.out.println("pre visit dir:" + dir);
    return FileVisitResult.CONTINUE;
  }

  @Override
  public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
    System.out.println("visit file: " + file);
    return FileVisitResult.CONTINUE;
  }

  @Override
  public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
    System.out.println("visit file failed: " + file);
    return FileVisitResult.CONTINUE;
  }

  @Override
  public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
    System.out.println("post visit directory: " + dir);
    return FileVisitResult.CONTINUE;
  }
});

FileVisitor实现中的每个方法在遍历期间的不同时间被调用:

在访问任何目录之前调用preVisitDirectory()方法。 postVisitDirectory()方法在访问目录之后被调用。

visitFile()方法是在文件遍历期间访问的每个文件被调用的。 它不被称为目录 - 只有文件。 visitFileFailed()方法在访问文件失败的情况下被调用。 例如,如果您没有正确的权限,或其他问题出错。

四个方法中的每一个都返回一个FileVisitResult枚举实例。 FileVisitResult枚举包含以下四个选项:

  • CONTINUE
  • TERMINATE
  • SKIP_SIBLINGS
  • SKIP_SUBTREE
    通过返回这些值之一,被调用的方法可以决定文件的走向应该如何继续。

继续意味着文件散步应该照常继续。

TERMINATE表示文件散步现在应该终止。

SKIP_SIBLINGS表示应该继续执行文件,但不访问此文件或目录的任何兄弟。

SKIP_SUBTREE表示文件行走应继续,但不访问此目录中的条目。 如果从preVisitDirectory()返回,此值只有一个函数。 如果从其他方法返回,它将被解释为CONTINUE。

搜索文件

下面是一个walkFileTree(),它扩展了SimpleFileVisitor以查找一个名为README.txt的文件:

Path rootPath = Paths.get("data");
String fileToFind = File.separator + "README.txt";

try {
  Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
    
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
      String fileString = file.toAbsolutePath().toString();
      //System.out.println("pathString = " + fileString);

      if(fileString.endsWith(fileToFind)){
        System.out.println("file found at path: " + file.toAbsolutePath());
        return FileVisitResult.TERMINATE;
      }
      return FileVisitResult.CONTINUE;
    }
  });
} catch(IOException e){
    e.printStackTrace();
}
递归删除目录

Files.walkFileTree()也可以用来删除一个包含所有文件和子目录的目录。 Files.delete()方法只会删除一个目录,如果它是空的。 通过遍历所有目录并删除每个目录中的所有文件(在visitFile()内),然后删除目录本身(在postVisitDirectory()内),可以删除包含所有子目录和文件的目录。 这是一个递归目录删除的例子:

Path rootPath = Paths.get("data/to-delete");

try {
  Files.walkFileTree(rootPath, new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
      System.out.println("delete file: " + file.toString());
      Files.delete(file);
      return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
      Files.delete(dir);
      System.out.println("delete dir: " + dir.toString());
      return FileVisitResult.CONTINUE;
    }
  });
} catch(IOException e){
  e.printStackTrace();
}

文件类中的其他方法

java.nio.file.Files类包含许多其他有用的功能,比如创建符号链接,确定文件大小,设置文件权限等功能。查看java.nio.file.Files类的JavaDoc以获取更多信息 这些方法。

相关文章
|
4月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
17天前
|
Java
让星星⭐月亮告诉你,Java NIO之Buffer详解 属性capacity/position/limit/mark 方法put(X)/get()/flip()/compact()/clear()
这段代码演示了Java NIO中`ByteBuffer`的基本操作,包括分配、写入、翻转、读取、压缩和清空缓冲区。通过示例展示了`position`、`limit`和`mark`属性的变化过程,帮助理解缓冲区的工作原理。
21 2
|
2月前
|
存储 网络协议 Java
Java NIO 开发
本文介绍了Java NIO(New IO)及其主要组件,包括Channel、Buffer和Selector,并对比了NIO与传统IO的优势。文章详细讲解了FileChannel、SocketChannel、ServerSocketChannel、DatagramChannel及Pipe.SinkChannel和Pipe.SourceChannel等Channel实现类,并提供了示例代码。通过这些示例,读者可以了解如何使用不同类型的通道进行数据读写操作。
Java NIO 开发
|
3月前
|
Java
"揭秘Java IO三大模式:BIO、NIO、AIO背后的秘密!为何AIO成为高并发时代的宠儿,你的选择对了吗?"
【8月更文挑战第19天】在Java的IO编程中,BIO、NIO与AIO代表了三种不同的IO处理机制。BIO采用同步阻塞模型,每个连接需单独线程处理,适用于连接少且稳定的场景。NIO引入了非阻塞性质,利用Channel、Buffer与Selector实现多路复用,提升了效率与吞吐量。AIO则是真正的异步IO,在JDK 7中引入,通过回调或Future机制在IO操作完成后通知应用,适合高并发场景。选择合适的模型对构建高效网络应用至关重要。
67 2
|
3月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
98 0
|
4月前
|
安全 Java Linux
(七)Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析!
IO(Input/Output)方面的基本知识,相信大家都不陌生,毕竟这也是在学习编程基础时就已经接触过的内容,但最初的IO教学大多数是停留在最基本的BIO,而并未对于NIO、AIO、多路复用等的高级内容进行详细讲述,但这些却是大部分高性能技术的底层核心,因此本文则准备围绕着IO知识进行展开。
147 1
|
3月前
|
存储 网络协议 Java
【Netty 神奇之旅】Java NIO 基础全解析:从零开始玩转高效网络编程!
【8月更文挑战第24天】本文介绍了Java NIO,一种非阻塞I/O模型,极大提升了Java应用程序在网络通信中的性能。核心组件包括Buffer、Channel、Selector和SocketChannel。通过示例代码展示了如何使用Java NIO进行服务器与客户端通信。此外,还介绍了基于Java NIO的高性能网络框架Netty,以及如何用Netty构建TCP服务器和客户端。熟悉这些技术和概念对于开发高并发网络应用至关重要。
63 0
|
4月前
|
安全 Java
【Java】已解决java.nio.channels.OverlappingFileLockException异常
【Java】已解决java.nio.channels.OverlappingFileLockException异常
103 1
|
4月前
|
Java
【Java】已解决java.nio.channels.ClosedChannelException异常
【Java】已解决java.nio.channels.ClosedChannelException异常
326 1
|
4月前
|
Java
【Java】已解决java.nio.channels.FileLockInterruptionException异常
【Java】已解决java.nio.channels.FileLockInterruptionException异常
35 1