java.nio.channels.ScatteringByteChannel Example

ScatteringByteChannel is an interface extends ReadableByteChannel and is defined in java.nio.channels package.

This is a channel that can read bytes into a sequence of buffers.

This interface defines two read methods.

 

Want to be a Java NIO Master ?
Subscribe to our newsletter and download the JDBC Ultimate Guide right now!
In order to help you master Java NIO Library, we have compiled a kick-ass guide with all the major Java NIO features and use cases! Besides studying them online you may download the eBook in PDF format!

Thank you!

We will contact you soon.


 
Both the methods return number of bytes read as a long.

This interface is implemented in the following channel classes defined within the same package: DatagramChannel, FileChannel, Pipe.SourceChannel and SocketChannel.

Scattering Read

A scattering read is like a regular channel read, except that it reads data into an array of ByteBuffers rather than a single buffer. Scattering reads are often useful when implementing network protocols or file formats that, for example, group data into segments consisting of one or more fixed-length headers followed by a variable-length body.

Scattering allows efficient reads which are:

This article shows a usage example with a FileChannel reading data from a file into buffer arrays.

NOTE: Also see the article java.nio.channels.FileChannel Example.

1. The Example

A program reads a file with a certain pre-defined format using a file channel. The channel’s read operation uses buffer arrays.

The example uses a data file to read. The file’s data is of the following format:

The example has two programs: FileChannelScatterReader.java and TestFileCreator.java

The TestFileCreator program creates a file “examplefile” using the RandomAccessFile class. The program’s code is not detailed here but a copy of the source is included (see the section 5. Download Java Source Code). The test data used in this example is shown later in this article (see the section 3. The Test Data).

The FileChannelScatterReader program reads the “examplefile” file. The program reads one record at a time using the FileChannel class’s read() method that takes a ByteBuffer array as parameter. Note that this read() method is inherited from the ScatteringByteChannel interface.

The following code snippets show the program process steps:

1.1. Create a channel

RandomAccessFile raf = new RandomAccessFile("examplefile", "r");
FileChannel channel = raf.getChannel();

1.2. Read the file header

Read and get the number of records in the file.

ByteBuffer buffer = ByteBuffer.allocate(4);
fileChannel.read(buffer);
buffer.flip();
int noOfRecords = buffer.getInt();

1.3. Read each record

First, the record header is read as follows. Note the usage of the buffer array and reading two fields in one read operation.

ByteBuffer buff1 = ByteBuffer.allocate(4);
ByteBuffer buff2 = ByteBuffer.allocate(4);
ByteBuffer [] buffs = {buff1, buff2};
channel.read(buffs);
			
buff1.flip();
int dataSize = buff1.getInt();	
buff2.flip();
int fileSize = buff2.getInt();

Next, read the two variable length data fields in one read operation using the first read’s output – the text data size and file size. The read operation uses the buffer array.

buff1 = ByteBuffer.allocate(dataSize);
buff2 = ByteBuffer.allocate(fileSize);		
buffs = new ByteBuffer [] {buff1, buff2};
channel.read(buffs);
			
// get data
byte [] bytes = buff1.array();
String data = new String(bytes);
// get file, if exists
if (fileSize > 0) {
    byte [] file = buff2.array();
    Path filePath = Paths.get((i+1) + "file.pdf");
    Files.write(filePath, file, StandardOpenOption.CREATE);
}

2. The Code

FileChannelScatterReader.java

import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
public class FileChannelScatterReader {
    public static void main (String [] args)
            throws Exception {
	
        new FileChannelScatterReader().readFile();
    }
	
    private void readFile()
            throws IOException {
        RandomAccessFile raf = new RandomAccessFile("examplefile", "r");
        FileChannel channel = raf.getChannel();
        System.out.println("File channel open. Reading file...");
		
        ByteBuffer buffer = ByteBuffer.allocate(4);
        channel.read(buffer);
        buffer.flip();
        int noOfRecords = buffer.getInt();
        System.out.println("Number of records: " + noOfRecords);		
		
        for (int i = 0; i < noOfRecords; i++) {
		
            // get text data size and file size
			
            ByteBuffer buff1 = ByteBuffer.allocate(4);
            ByteBuffer buff2 = ByteBuffer.allocate(4);
            ByteBuffer [] buffs = {buff1, buff2};
            channel.read(buffs);
			
            buff1.flip();
            int dataSize = buff1.getInt();
            System.out.println((i+1) + " Text data size: " + dataSize);
			
            buff2.flip();
            int fileSize = buff2.getInt();
            System.out.println((i+1) + " File data size: " + fileSize);			
		
            // get text and file data
			
            buff1 = ByteBuffer.allocate(dataSize);
            buff2 = ByteBuffer.allocate(fileSize);
			
            buffs = new ByteBuffer [] {buff1, buff2};
            channel.read(buffs);
			
            // get text
            byte [] bytes = buff1.array();
            String data = new String(bytes);
            System.out.println((i+1) + " Text data: " + data);
			
            // get file, if exists
            if (fileSize > 0) {
                byte [] file = buff2.array();
                System.out.println((i+1) + " Read file size: " + file.length);
                Path filePath = Paths.get((i+1) + "file.pdf");
	        Files.write(filePath, file, StandardOpenOption.CREATE);
                System.out.println((i+1) + " File: " + filePath.getFileName());
            }
        }
        channel.close();
        System.out.println("Closing channel.");
    }
}

3. The Test Data

This sample data is created using the TestFileCreator.java class. The following is the data:

Number of records: 3
1st record:
Headers (data size and filesize): 10 and 16423
Data: 1234567890
File: a PDF file
2nd record:
Headers (data size and filesize): 4 and 0
Data: 1234
File: none
3rd record:
Headers (data size and filesize): 8 and 0
Data: 12345678
File: none

Note that a PDF file is required as test data file for the 1st record. Rename the file as “file1.pdf”. A copy of the program TestFileCreator.java is included in the source code download ZIP file (see the section 5. Download Java Source Code).

4. The Output

File channel open. Reading file...
Number of records: 3
1 Text data size: 10
1 File data size: 16423
1 Text data: 1234567890
1 Read file size: 16423
1 File: 1file.pdf
2 Text data size: 4
2 File data size: 0
2 Text data: 1234
3 Text data size: 8
3 File data size: 0
3 Text data: 12345678
Closing the channel.

From the output:

5. Download Java Source Code

This was an example of java.nio.channels.ScatteringByteChannel

Download
You can download the full source code of this example here: ScatteringByteChannelExample.zip
Exit mobile version