o7planning

Java WritableByteChannel Tutorial with Examples

  1. WritableByteChannel
  2. Methods
  3. write(ByteBuffer src)
  4. Example 1

1. WritableByteChannel

If you are just getting started with Java NIO, read the following articles first to understand more about the basics:
  • Java Nio
WritableByteChannel is an interface that extends from the Channel interface, which represents channels that can write bytes to an IO device.
public interface WritableByteChannel extends Channel
Compared to the parent inteface, WritableByteChannel provides only one more method to write bytes from a ByteBuffer to this Channel.
public int write(ByteBuffer src) throws IOException;
Only one write operation on the Channel can take place at a time. This means that if one thread is initiating a write operation on a Channel, other threads cannot write on this Channel, they are blocked until the operation is completed. Other IO operations can be performed concurrently with the write operation depending on the Channel type.
Hierarchy of interfaces and classes related to WritableByteChannel:

2. Methods

WritableByteChannel provides only one more method than its parent interface.
public int write(ByteBuffer src) throws IOException;
Other methods inherit from the Channel interface:
public boolean isOpen();  
public void close() throws IOException;

3. write(ByteBuffer src)

public int write(ByteBuffer byteBuffer) throws IOException;
The write(ByteBuffer) method writes a sequence of bytes between position and limit-1 on the specified ByteBuffer to this Channel. It will write as much as possible and return the number of bytes written.
  • Each byte written to this Channel will increase the cursor position on the ByteBuffer by 1.
  • Before calling this method you should call ByteBuffer.clear() method to set position = 0 and limit = capacity.
  • The maximum number of bytes that can be written in one call of this method is byteBuffer.limit()-byteBuffer.position().
The method will attempt to write all bytes from position to limit-1 into this Channel. However, some Channel(s) types such as SocketChannel, depending on its state, may only have a few bytes written to. So you need to write code like below to ensure that all bytes are successfully written:
while(byteBuffer.hasRemaining())  {
    channel.write(byteBuffer);
}
Only one write operation on the Channel can take place at a time. This means that if one thread is initiating a write operation on a Channel, other threads cannot write on this Channel, they are blocked until the operation is completed. Other IO operations can be performed concurrently with the write operation depending on the Channel type.

4. Example 1

Example: Use WritableByteChannel to write data to a file.
WritableByteChannel_ex1.java
package org.o7planning.writablebytechannel.ex;

import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;

public class WritableByteChannel_ex1 {
    // Windows: "C:/somepath/out-file.txt";
    private static final String outFilePath = "/Volumes/Data/test/out-file.txt";

    public static void main(String[] args) throws IOException {  
        OutputStream outputStream = null;
        WritableByteChannel channel = null;
        try {
            byte[] byteData = "JP日本-八洲".getBytes("UTF-8");
            
            File outFile = new File(outFilePath);
            outFile.getParentFile().mkdirs(); // Make sure parent folder is exists.
            outputStream = new FileOutputStream(outFile);
            
            // Create WritableByteChannel to write data to an OutputStream.
            channel = Channels.newChannel(outputStream);
            
            ByteBuffer buffer = ByteBuffer.allocate(byteData.length);
            buffer.put(byteData);
            // Set limit = current position and position = 0;
            buffer.flip();
            
            while(buffer.hasRemaining())  {
                channel.write(buffer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            closeQuietly(outputStream);
            closeQuietly(channel);
        }
    }

    private static void closeQuietly(Closeable closeable) {
        try {
            closeable.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Both OutputStream and Channel implement or extend from the Closeable interface, so it has the ability to automatically close if you use the "Closeable-try-catch" syntax. And we rewrite the above example more succinctly.
WritableByteChannel_ex1b.java
package org.o7planning.writablebytechannel.ex;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;

public class WritableByteChannel_ex1b {
    // Windows: "C:/somepath/out-file.txt";
    private static final String outFilePath = "/Volumes/Data/test/out-file.txt";

    public static void main(String[] args) throws IOException {
        File outFile = new File(outFilePath);
        outFile.getParentFile().mkdirs(); // Make sure parent folder is exists.

        // Closeable-try-catch Syntax:
        try (OutputStream outputStream = new FileOutputStream(outFile);
                // Create WritableByteChannel to write data to an OutputStream.
                WritableByteChannel channel = Channels.newChannel(outputStream);) { // try

            byte[] byteData = "JP日本-八洲".getBytes("UTF-8");
            ByteBuffer buffer = ByteBuffer.allocate(byteData.length);
            buffer.put(byteData);
            // Set limit = current position and position = 0;
            buffer.flip();

            while (buffer.hasRemaining()) {
                channel.write(buffer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • Java Closeable