ScatteringByteChannel

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.

  • read(ByteBuffer [] dsts): Reads a sequence of bytes from this channel into the given buffers.
  • read(ByteBuffer [] dsts, int offset, int length): Reads a sequence of bytes from this channel into a sub-sequence of the given buffers.

 

 
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:

  • atomic: where a set of data can be read as single read operation
  • segments: data can be segmented as required into the buffers

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:

  • File header, an integer, specifies the number of records in the file. The record data follows.
  • Each record has a record header and data.
  • The record header has two integer fields; they specify the length of the two respective data fields.
  • The data has two variable length fields. The first field is plain text and the second is binary data (like a PDF file).

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:

  • Number of records: 3. This is the file header data.
  • The following is the 1st record data. Note the record number is prefixed to each output line.
    1 Text data size: 10
    1 File data size: 16423
    1 Text data: 1234567890
    1 Read file size: 16423
    1 File: 1file.pdf
  • The 2nd and 3rd record data is similar and without the file data.

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

Prasad Saya

Prasad Saya is a software engineer with over ten years’ experience in application development, maintenance, testing and consulting on various platforms. He is a certified Java and Java EE developer. At present his interest is in developing Java applications. He also has experience working with databases and ERP applications.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button