为什么 StandardOpenOption.CREATE_NEW 不创建要在 Java 中读取的文件?

Shr*_*hri 3 java file-handling java-nio

这是我的代码:

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class ExplicitChannelRead {

    public static void main(String[] args) {
        
        int count;
        Path filePath = null;
        
        // First, obtain a path to a file.
        try {
            filePath = Paths.get("test1.txt");
        }
        catch(InvalidPathException e) {
            System.out.println("Path error: "+e);
            return;
        }
        
        // Next, obtain a channel to that file within a try-with-resources block.
        try(SeekableByteChannel fChan = 
                Files.newByteChannel(filePath, StandardOpenOption.CREATE_NEW)) {
            
            // Allocate a buffer.
            ByteBuffer mBuf = ByteBuffer.allocate(128);
            
            while((count=fChan.read(mBuf)) != -1) {
                
                //Rewind the buffer so that it can be read.
                mBuf.rewind();
                
                for(int i=0; i<count; i++) System.out.print((char)mBuf.get());
                
            }
            
            System.out.println();
            
            
        } catch (IOException e) {
            e.printStackTrace();
//          System.out.println("I/O error: "+e);
        }
        

    }

}
Run Code Online (Sandbox Code Playgroud)

运行上面的代码时我得到这个异常:

java.nio.file.NoSuchFileException: test1.txt
    at java.base/sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:85)
    at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:103)
    at java.base/sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:108)
    at java.base/sun.nio.fs.WindowsFileSystemProvider.newByteChannel(WindowsFileSystemProvider.java:235)
    at java.base/java.nio.file.Files.newByteChannel(Files.java:375)
    at java.base/java.nio.file.Files.newByteChannel(Files.java:426)
    at fileNIO.ExplicitChannelRead.main(ExplicitChannelRead.java:31)
Run Code Online (Sandbox Code Playgroud)

我不明白为什么未创建 test1.txt 文件,因为它当前不存在并且我正在使用 StandardOpenOption.CREATE_NEW 选项?

当我将 StandardOpenOption.WRITE 选项与 StandardOpenOption.CREATE_NEW 一起使用时,我看到正在创建文件 text1.txt,当时我收到异常:

线程“main”中的异常 java.nio.channels.NonReadableChannelException

这个异常我理解它的原因,因为我已经以写入模式打开了文件,并且在代码中我正在对文件执行读取操作。

在我看来,以读取模式打开文件时无法创建新文件。

Ste*_*n C 5

我已经重现了您所看到的内容(在带有 Java 17 的 Linux 上)。

正如我在评论中指出的,这种行为似乎与 javadocs 所说的应该发生的情况相矛盾,但我发现的是:

  • READ或 两者都不存在READ或 时,将抛出WRITEa 。NoSuchFileException

  • 使用WRITE(或不使用READ)时,文件会被创建,但随后NonReadableChannelException会被抛出。

  • READ和一起使用WRITE,它可以工作。至少……对我来说是这样。

我想这是有道理的。您需要READ读取该文件并WRITE创建它。javadoc 声明READ如果您不指定READ,WRITE或 ,则这是默认值APPEND

但是创建一个空文件1然后CREATE_NEW立即尝试读取它是一个近乎毫无意义的用例。因此,他们没有(清楚地)记录如何实现这一目标并不完全令人惊讶。


1 - 正如评论所述,CREATE_NEW如果文件已存在,则指定失败。如果您想要“如果不存在则创建它”,那么您应该使用CREATE