Scatter Gather

Java-Scatter and Gather

Scatter and Gather

Channels provide an important new capability known as scatter/gather. Scatter/gather is a simple yet powerful concept. It refers to performing a single I/O operation across multiple buffers. For a write operation, data is gathered (drained) from several buffers in turn and sent along the channel. The buffers do not need to have the same capacity. The effect is the same as if the content of all the buffers was concatenated into one large buffer before being sent.

gather

For reads, the data read from the channel is scattered to multiple buffers in sequence, filling each to its limit, until the data from the channel or the total buffer space is exhausted.


Java provides the ScatteringByteChannel interface to support scattering and the GatheringByteChannel interface to support gathering.

ScatteringByteChannel Methods

Method Description
long   read(ByteBuffer[] dsts) Reads a sequence of bytes from this channel into the given buffers and returns the number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream.
long   read(ByteBuffer[] dsts,                  int offset, int length) Reads a sequence of bytes from this channel into a subsequence of the given buffers and returns the number of bytes read, possibly zero, or -1 if the channel has reached end-of-stream.

GatheringByteChannel Methods

Method Description
long   write(ByteBuffer[] srcs) Writes a sequence of bytes to this channel from the given buffers and returns the number of bytes written, possibly zero.
long   write(ByteBuffer[] srcs,                  int offset, int length) Writes a sequence of bytes to this channel from a subsequence of the given buffers and returns the number of bytes written, possibly zero.

The following program demonstrates the Scatter/gather. The main( ) method first obtains a scattering byte channel by instantiating FileInputStream and passing this instance to the Channels class’s ReadableByteChannel newChannel(InputStream inputStream) method. The returned ReadableByteChannel instance is cast to ScatteringByteChannel because this instance is actually a FileChannel that implements ScatteringByteChannel.

casting
Next, main() creates three byte buffers; the first buffer has a capacity of 10 bytes, second buffer has a capacity of 10 bytes and the thrid buffer has a capacity of 6 bytes. These buffers are subsequently stored in an array and this array is passed to read(ByteBuffer[]) to fill them. After filling the buffers, main( ) flips them so that it can output their contents to standard output(console screen). After these contents have been output, the buffers are rewound in preparation for being drained via a gather operation.

Next, main() now obtains a gathering byte channel by instantiating FileOutputStream and passing this instance to the Channels class’s WritableByteChannel newChannel(OutputStream outputStream) method. The returned WritableByteChannel instance is cast to GatheringByteChannel because this instance is actually a FileChannel that implements GatheringByteChannel.

casting
Finally, main() passes this array to write(ByteBuffer[]) to drain them.

Program

output

Program Source

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ScatteringByteChannel;
import java.nio.channels.GatheringByteChannel;
import java.io.IOException;

public class Javaapp {

    public static void main(String[] args) throws IOException {
        
        FileInputStream filein = new FileInputStream("data1.txt");
        ScatteringByteChannel src = (ScatteringByteChannel)Channels.newChannel(filein);
        ByteBuffer buf1 = ByteBuffer.allocate(10);
        ByteBuffer buf2 = ByteBuffer.allocate(10);
        ByteBuffer buf3 = ByteBuffer.allocate(6);
        ByteBuffer bufarray[] = {buf1,buf2,buf3};
        src.read(bufarray);
        buf1.flip();
        buf2.flip();
        buf3.flip();
        int i=0;
        while(i<bufarray.length)
        {
            while(bufarray[i].hasRemaining())
            {
                System.out.print((char)bufarray[i].get()+" ");
            }
            System.out.println();
            i++;
        }
        buf1.flip();
        buf2.flip();
        buf3.flip();
        FileOutputStream fileout = new FileOutputStream("data2.txt");
        GatheringByteChannel dest = (GatheringByteChannel)Channels.newChannel(fileout);
        dest.write(bufarray);
        src.close();
        dest.close();
    }
}

Leave a Comment