Thursday, April 9, 2015

Java NIO ByteBuffer Experiments

Me and Sunil Kalva stumbled upon an exciting use case for Java NIO ByteBuffers. Sunil started experimenting using the compiler, and I started reading on it. Java NIO documentations were not that great and found an excellent tutorial. Please go through the link and understand the bytebuffer jargon like capacity, position, limit, compact, clear etc before trying out this example. 

Code: 
 import java.nio.ByteBuffer;  
 public class test {  
  public static void main(String[] args) {  
   ByteBuffer byteBuffer = ByteBuffer.allocate(10);  
   print(byteBuffer, "ByteBuffer Created");  
   byteBuffer.put("ABCD".getBytes());  
   print(byteBuffer, "After adding data");  
   byteBuffer.flip();  
   print(byteBuffer, "After Read Flip");  
   System.out.println("Reading data from byte buffer");  
   while(byteBuffer.hasRemaining()){  
    System.out.print((char) byteBuffer.get());  
   }  
   //spacer  
   System.out.println();  
   print(byteBuffer, "After Reading ");  
   byteBuffer.rewind();  
   print(byteBuffer, "After rewind");  
   byteBuffer.compact();  
   print(byteBuffer, "After Compact");  
   byteBuffer.put("EFGHIJ".getBytes());  
   print(byteBuffer, "After Adding More");  
   byteBuffer.clear();  
   print(byteBuffer, "After clear");  
   byteBuffer.get(new byte[2]);  
   print(byteBuffer, "After Reading 2 bytes");  
   byteBuffer.compact();  
   print(byteBuffer, "After compact");  
   byteBuffer.put("LM".getBytes());  
   print(byteBuffer, "After Writing 2 bytes");  
  }  
  private static void print(ByteBuffer byteBuffer, String message) {  
   System.out.println("\n========= " + message + " ========= " );  
   System.out.println("Content  = "+new String(byteBuffer.array()));  
   System.out.println("Position = " + byteBuffer.position());  
   System.out.println("Limit   = " + byteBuffer.limit());  
   System.out.println("Remaining = " + byteBuffer.remaining());  
   System.out.println("======================================");  
   System.out.println();  
  }  
 } 

Output:
 ========= ByteBuffer Created =========   
 Content  =   
 Position = 0  
 Limit   = 10  
 Remaining = 10  
 ======================================  
 ========= After adding data =========   
 Content  = ABCD  
 Position = 4  
 Limit   = 10  
 Remaining = 6  
 ======================================  
 ========= After Read Flip =========   
 Content  = ABCD  
 Position = 0  
 Limit   = 4  
 Remaining = 4  
 ======================================  
 Reading data from byte buffer  
 ABCD  
 ========= After Reading =========   
 Content  = ABCD  
 Position = 4  
 Limit   = 4  
 Remaining = 0  
 ======================================  
 ========= After rewind =========   
 Content  = ABCD  
 Position = 0  
 Limit   = 4  
 Remaining = 4  
 ======================================  
 ========= After Compact =========   
 Content  = ABCD  
 Position = 4  
 Limit   = 10  
 Remaining = 6  
 ======================================  
 ========= After Adding More =========   
 Content  = ABCDEFGHIJ  
 Position = 10  
 Limit   = 10  
 Remaining = 0  
 ======================================  
 ========= After clear =========   
 Content  = ABCDEFGHIJ  
 Position = 0  
 Limit   = 10  
 Remaining = 10  
 ======================================  
 ========= After Reading 2 bytes =========   
 Content  = ABCDEFGHIJ  
 Position = 2  
 Limit   = 10  
 Remaining = 8  
 ======================================  
 ========= After compact =========   
 Content  = CDEFGHIJIJ  
 Position = 8  
 Limit   = 10  
 Remaining = 2  
 ======================================  
 ========= After Writing 2 bytes =========   
 Content  = CDEFGHIJLM  
 Position = 10  
 Limit   = 10  
 Remaining = 0  
 ======================================  



On carefully examining the values getting advanced for position and remaining pointers, we were able to get a decent understanding about the internals of a byte buffer during various operations.

Takeaways: 
  1. flip is used to switch to read mode from write mode
  2. rewind is used to re-read 
  3. clear is used to switch to write mode from read mode. In other words it is clearing the buffer to start writing
  4. compact is used to switch to append mode when we are in read mode. It starts appending from last read byte. And before that it moves all the unread bytes to the initial position of the byte buffer. Visualise it like the operating system doing a disk compaction. Everything fragmented comes to the extreme left in a compacted way.
  5. while(byteBuffer.hasRemaining()){byteBuffer.get()} can be used to exhaustively reading the byte buffer.
  6. A simple workflow will be like 
create;  
 repeat() {  
 put; // write  
 flip; // get ready to read  
 get; //read  
 clear; or compact; //get ready to write  
 }  

Have a fun time with bytebuffer just like we had. 

No comments:

Post a Comment