java - 我可以相信 Files 中的方法会在预期时抛出 NoSuchFileException 吗?

标签 java file-io nio

java.nio.file.Files API 是对旧的 java.io.File 类的一个非常好的改进,但有一个细节让我感到奇怪;除了 delete()没有方法记录它们可能会抛出 NoSuchFileException,甚至 delete() 都说这是可选的。

我希望能够区分由于丢失文件和其他 IO 问题导致的失败,但似乎不能保证这可能。

如果文件是在两个操作之间创建的,则预先调用 Files.exists() 等方法的替代方法会冒竞争条件的风险。

我能否期望 Files 中的方法会在适当的时候引发 NoSuchFileException?如果是这样,这在哪里记录?如果不是,我如何安全地确定故障是由于文件丢失造成的?


示例:在带有 Java 7.0.02 的 Windows 7 上 Files.readAllLines()方法确实会引发 NoSuchFileException,但没有明确记录这样做:

Files.readAllLines(Paths.get("foo"), StandardCharsets.UTF_8)
java.nio.file.NoSuchFileException: foo
  at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:79)
  at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
  at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
  at sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:229)
  at java.nio.file.Files.newByteChannel(Files.java:315)
  at java.nio.file.Files.newByteChannel(Files.java:361)
  at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:380)
  at java.nio.file.Files.newInputStream(Files.java:106)
  at java.nio.file.Files.newBufferedReader(Files.java:2660)
  at java.nio.file.Files.readAllLines(Files.java:2993)

最佳答案

一般来说:不,您不能相信 java.nio.file.Files 中的方法会在预期时抛出 NoSuchFileException,但您可以验证。

正如您从堆栈跟踪中看到的那样,Files 使用 FileSystemProvider执行文件操作。 FileSystemProvider 实现受到限制(如 WindowsFileSystemProvider )并且反过来使用大量 native (C) 代码。例如,我将 NoSuchFileException 追踪到 WindowsException它依赖于操作系统报告 ERROR_FILE_NOT_FOUNDERROR_PATH_NOT_FOUND。另一个例子是 newInputStream 路由,它来自 ChannelInputStreamWindowsChannelFactoryWindowsNativeDispatcher.c最后调用 native Windows 函数 CreateFileW .
考虑到仅适用于 Windows 的代码量,我看不出如何相信它可以像使用代码 here 的 Linux 一样工作。和 here .

根据我的经验,Linux (Posix) 文件系统行为非常一致,但 Windows (NT) 文件系统行为则不然:我不认为 Windows 7 的行为与 Windows 8 完全相同。

最后,关于竞争条件的评论:据我所知,没有任何文件系统可以保证目录中列出的文件确实存在(某些文件可能已经被删除,尤其是在对同一目录中的文件使用多个线程操作时)。根据我的经验,事先使用像 Files.exists() 这样的方法是一个坏主意,除非您要分配大量资源(例如,创建连接以上传文件)。处理文件时,最好假设一切都井井有条并捕获异常,然后尝试确定错误所在。例如。读取文件时,打开它而不检查文件是否存在,如果发现错误,请先检查文件是否存在。这可以节省大量 I/O 操作,进而有助于提高性能。

关于java - 我可以相信 Files 中的方法会在预期时抛出 NoSuchFileException 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29091968/

相关文章:

java - 启动时确定Axis2服务的文件系统路径

java - 在 Web 应用程序中运行时动态加载 Spring 上下文

java - 动态改变方法的返回类型

java - NIO:OP_READ并且未读取所有数据; OP_READ 是否仍处于就绪状态?

java - 使用 URI 类创建自定义 URI 方案

java - FileInputStream 和 OutputStream 无法在文件中读取和写入对象

java - 如何获取文件目录的绝对路径?

C语言计算文件行数

Filechannel TransferTO 的 Java 文档规范

java - 使用 Java 7 仅访问特定深度的目录