簡體   English   中英

FileChannel.open(path, CREATE|CREATE_NEW) 沒有 WRITE 選項會拋出 NoSuchFileException

[英]FileChannel.open(path, CREATE|CREATE_NEW) without WRITE option throws NoSuchFileException

我有以下代碼:


  @Nonnull
  @SneakyThrows
  private Pair<InputStream, Long> probeSize(@Nonnull final InputStream image) {
    final String tmpId = UUID.randomUUID().toString();
    final File probeFile = new File(tmpDir, tmpId + ".jpg");

    try (final FileChannel outChannel = FileChannel.open(probeFile.toPath(), CREATE);
         final ReadableByteChannel innChannel = Channels.newChannel(image)) {
      outChannel.transferFrom(innChannel, 0, Long.MAX_VALUE);
    }

    final Long fileSize = probeFile.length();
    return Pair.of(new FileInputStream(probeFile), fileSize);
  }

此代碼始終引發以下異常:

Caused by: java.nio.file.NoSuchFileException: /tmp/4bbc9008-e91c-4f18-b0f2-c61eed35066e.jpg
    at sun.nio.fs.UnixException.translateToIOException(Unknown Source)
    at sun.nio.fs.UnixException.rethrowAsIOException(Unknown Source)
    at sun.nio.fs.UnixException.rethrowAsIOException(Unknown Source)
    at sun.nio.fs.UnixFileSystemProvider.newFileChannel(Unknown Source)

查看FileChannel.open(path, option)的 javadoc 和相關的StandardOpenOption ,沒有文檔暗示要創建文件,還必須打開它進行寫入。

唯一有效的選項:

  • FileChannel.open(probeFile.toPath(), CREATE, WRITE)
  • FileChannel.open(probeFile.toPath(), CREATE_NEW, WRITE)

我只是通過UnixChannelFactory.newFileChannel確定了這一點,並注意到以下內容:

UnixChannelFactory:

protected static FileDescriptor open(int dfd,
                                         UnixPath path,
                                         String pathForPermissionCheck,
                                         Flags flags,
                                         int mode)
        throws UnixException
    {
        // map to oflags
        int oflags;
        if (flags.read && flags.write) {
            oflags = O_RDWR;
        } else {
            oflags = (flags.write) ? O_WRONLY : O_RDONLY;
        }
        if (flags.write) {
            if (flags.truncateExisting)
                oflags |= O_TRUNC;
            if (flags.append)
                oflags |= O_APPEND;

            // create flags
            if (flags.createNew) {
                byte[] pathForSysCall = path.asByteArray();

                // throw exception if file name is "." to avoid confusing error
                if ((pathForSysCall[pathForSysCall.length-1] == '.') &&
                    (pathForSysCall.length == 1 ||
                    (pathForSysCall[pathForSysCall.length-2] == '/')))
                {
                    throw new UnixException(EEXIST);
                }
                oflags |= (O_CREAT | O_EXCL);
            } else {
                if (flags.create)
                    oflags |= O_CREAT;
            }
        }

這表明,除非您指定WRITE選項,否則將永遠不會創建該文件。

這是一個錯誤還是一個預期的功能, FileChannel.open除非打開以進行寫入,否則無法創建文件?

我正在查看FileChannel.open(...)的 JDK 7 Javadoc

該方法的文檔說:

READWRITE選項確定是否應打開文件進行讀取和/或寫入。 如果數組中不包含任何選項(或APPEND選項),則打開文件進行讀取。

CREATE_NEW的文檔說:

當文件只為閱讀而打開時,此選項將被忽略。

CREATE的文檔說:

如果CREATE_NEW選項也存在或文件打開僅用於讀取,則忽略此選項。

將這三個片段放在一起,是的,這是預期的行為。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM