Search code examples
javanio

What is the function of the WRITE options when given to Files.newOutputStream


When opening an OutputStream using the Files API you can pass options for it. One of the options is WRITE which is applied by default if no options are specified. However I fail to see what the difference is when it is provided and when it is not. An outputstream can only be used for writing, no? The docs only mention:

Open for write access.

An outputstream is per definition always to write content so I fail to so the use for it. In our project (where we had a bug related to the TRUNCATE_EXISTING missing) the WRITE option was not specified but the file was (over)written either anyway. To be clear, what is the difference between:

// OpenOption.CREATE, OpenOption.TRUNCATE_EXISTING, OpenOption.WRITE
Files.newOutputStream(file); 

and

Files.newOutputStream​(file, OpenOption.CREATE, OpenOption.TRUNCATE_EXISTING);

Solution

  • The Files.newOutputStream() method ends up calling FileSystemProvider.newStreamOutput(), which uses newByteChannel() to create the OutputStream as can be seen in the source code:

        public OutputStream newOutputStream(Path path, OpenOption... options)
            throws IOException
        {
            int len = options.length;
            Set<OpenOption> opts ;
            if (len == 0) {
                opts = DEFAULT_OPEN_OPTIONS;
            } else {
                opts = new HashSet<>();
                for (OpenOption opt: options) {
                    if (opt == StandardOpenOption.READ)
                        throw new IllegalArgumentException("READ not allowed");
                    opts.add(opt);
                }
                opts.add(StandardOpenOption.WRITE);
            }
            WritableByteChannel wbc = newByteChannel(path, opts);
            if (wbc instanceof FileChannelImpl) {
                ((FileChannelImpl) wbc).setUninterruptible();
            }
            return Channels.newOutputStream(wbc);
        }
    

    This method always adds WRITE to the options. Note that DEFAULT_OPEN_OPTIONS, used when no options at all are given, also contains WRITE.

    The newByteChannel() method requires WRITE (or APPEND) to create a writeable channel. Partial documentation:

    Opens or creates a file, returning a seekable byte channel to access the file.

    The options parameter determines how the file is opened. The READ and WRITE options determine if the file should be opened for reading and/or writing. If neither option (or the APPEND option) is present then the file is opened for reading. By default reading or writing commence at the beginning of the file.

    The default options - CREATE, TRUNCATE_EXISTING and WRITE - are used if no options are provided as argument. So the WRITE option can be used to avoid these default options from being used. For example if the file should not be emptied (truncated) when opened.