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

标签 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);
        }
        

    }

}

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

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)

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

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

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

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

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

最佳答案

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

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

  • 使用READREADWRITE 时,将抛出NoSuchFileException

  • 使用WRITE(没有READ),文件被创建,但随后抛出NonReadableChannelException

  • READWRITE 都可以。至少……它对我有用。

我想这是有道理的。您需要 READ 来读取文件,并需要 WRITE 来创建文件。如果您不指定 READWRITEAPPEND,javadocs 声明 READ 是默认值。

但是使用 CREATE_NEW 创建一个空文件1 然后立即尝试读取它是一个近乎毫无意义的用例。因此,他们没有(清楚地)记录如何实现这一点也就不足为奇了。


1 - 如评论所述,CREATE_NEW 被指定为在文件已存在时失败。如果你想“如果它不存在就创建它”,那么你应该改用 CREATE

关于java - 为什么 StandardOpenOption.CREATE_NEW 不创建要在 Java 中读取的文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73018672/

相关文章:

c - 在C中以十六进制读取文件内容

c++ - g++ 9.2.1 (Linux) 导致段错误,但 Windows 上的代码块不会

java - Java 中 File.exists() 的替代方案

java - Dagger2 对待 @Singleton 和自定义 sopes 的方式有区别吗?

java - 通过 addMouseListener 添加时如何检测鼠标点击 menuItem

java - 将数组对象传递给 jdbc 查询

java - 将数据写回二进制文件

c - 将文件的内容逐行加载到 C 中的数组中