Search code examples
javaioniobytebuffer

How to write a reader into a file using nio?


Given a Reader, a Charset, and a Path, how do I correctly and efficiently write the reader's content into a file?

The total size of the reader's content is not known in advance.

This is my current solution:

CharBuffer charBuffer = CharBuffer.allocate(1024);

try (FileChannel fc = (FileChannel) Files.newByteChannel(path, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)) {
    while (true) {
        int size = reader.read(charBuffer);
        if (size < 0) break;
        charBuffer.flip();
        ByteBuffer bytes = charset.encode(charBuffer);
        fc.write(bytes);
        charBuffer.flip();
    }
}

It works but it allocates a new ByteBuffer in every loop. I could try to reuse the byte buffer, but I would actually prefer a solution that uses only one buffer in total.

Using ByteBuffer#toCharBuffer is not an option because it does not consider the charset.

I also don't like the type cast in the try-statement, is there a cleaner solution?


Solution

  • The simplest way to transfer reader to a path is to use the built in methods of Files:

    try(var out = Files.newBufferedWriter(path, charset, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW)) {
        reader.transferTo(out);
    }
    

    This does not need the CharBuffer and simplifies the logic of the code you need to write for this often needed task.