Home : Course Map : Chapter 9 : Java : Advanced :
More NIO:
Using ByteBuffer to Convert Bytes to/from Primitive Types
JavaTech
Course Map
Chapter 9

Introduction
Overview
Streams
Wrappers,Buffers
Console I/O
  Text Output 
     Demo 1

  Formatter/printf()
     Demo 2

  Tex 2t Input
     Demo 3

  Scanner
     
Demo 4
File Class
  File I/O
  File Output-Text
     Demo 5

  Formatter to File
     Demo 6

  File Input - Text
    Demo 7

  Scanner - Files
     Demo 8

  File I/O - Binary
     Demo 9
   Demo 10
File Chooser Dialog
  Demo 11

Character Codes
  Demo 12
   Demo13
Object I/O
Types to Bytes
Stream Filters
Other I/O Topics
Exercises

    Supplements
Character I/O
  Demo 1   Demo 2
Random Access
  Demo 3
ZIP/GZIP Streams
  Demo 4
Piped Streams
  Demo 5
NIO Framework
More NIO
  Demo 6

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

In Chapter 9: Java: Converting Primitive Type Data to Bytes and Back, we discuss how to use the byte array input and output streams to treat different sections of a byte array as primitive type data. In Chapter 9: Tech: Histogram I/O, we show how to use this technique in a program.An alternative for this sort of byte handling is provided by the NIO buffers.

For each of the primitive types, the ByteBuffer class has a set of get and put methods such as these for the int type:

int getInt()
int getInt(int index)
void putInt (int data)
void putInt (int index, int data)

The getInt() method returns an int value using the four bytes starting from the current position in the buffer. The position value will be increment by four after this operation. The getInt(int index) method uses the argument as the position in the buffer from where an int value will be obtained from four consecutive bytes. Similarly, the put methods insert data at the current position or the absolute position.

Another way to handle the bytes in ByteBuffer as other primitive types is via the view buffers obtained from these methods:

CharBuffer   asCharBuffer()
ShortBuffer  asShortBuffer()
IntBuffer    asIntBuffer()
LongBuffer   asLongBuffer()
FloatBuffer  asFloatBuffer()
DoubleBuffer asDoubleBuffer()

For these methods, starting from the current position, a buffer will be returned that treats the bytes in the ByteBuffer as the indicated primitive type. This is convenient since the indexing for put/get operations will correspond to the locations of the primitive type values rather than byte index. Also, bulk put/get operations will treat the buffer as groups of the primitive type. If the ByteBuffer is a direct buffer, then the view buffers also will be direct.

We illustrate how to use these methods by modifying the example program in Chapter 9: Tech: Histogram I/O. Most of the code is identical to that used there except for two classes. The primary class HistIOApp is replaced by HistNIOApp, which differs only in the name and with four static references to HistIOTools replacecd with HistNIOTools.

The HistNIOTools class is the same as HistIOTools except for the methods readFile(), writeFile()
packHistogram()
, and unpackHistogram(), which use the above methods to pack and unpack a mix of data types for saving and retrieving a histogram to and from a disk file.

HistNIOApp same as HistIOApp discussed in Chapter 9: Tech: Histogram I/O.
HistNIOTools -shown below.

import javax.swing.*;
import java.io.*;
import java.nio.*;
import java.nio.channels.*;

/**
  * This class contains several static methods used to
  * write and read histograms to disk files. It is identical
  * to HistIOTools class except for the following four
  * methods, which use NIO techniques:
  *
  * readFile(), writeFile()
  * packHistogram(), unpackHistogram()
  *
**/
public class HistNIOTools {

     ... This code section is identical to that in HistIOTools.

  /**
    * Use a FileChannel to read to read the histogram data
    * from the given file.
    *
    * @param file File object from which to locate file.
   **/
  public static Histogram readFile (File file) {

    try {

      FileChannel in_chan = new FileInputStream (file).getChannel ();

      // Assume histogram file sizes are always less than int max.
      int num_data = (int) in_chan.size ();

      ByteBuffer buffer = ByteBuffer.allocateDirect (num_data);
      in_chan.read (buffer);
      in_chan.close ();

      return unpackHistogram (buffer);

    } catch (IOException ioe ) {
      JOptionPane.showMessageDialog (
            null,
            "Error in reading data!!\n\r"+ioe,
            "Histogram File Read Error",
            JOptionPane.ERROR_MESSAGE);
      return null;
    }
  } // readFile

  /**
    * Use a FileChannel to write a ByteBuffer containing the
    * histogram data to the given file.
    *
    * @param file File object for the file to receive the histogram data.
   **/
  public static boolean writeFile (File file, Histogram histogram) {

    ByteBuffer buffer = packHistogram (histogram);
    try {
      FileChannel out_chan = new FileOutputStream (file).getChannel();
      out_chan.write (buffer);
      out_chan.close ();
    }
    catch  (IOException ioe) {
      JOptionPane.showMessageDialog (
                  null,
                  "Error in writing data!!\n\r"+ioe,
                  "Histogram File Save Error",
                  JOptionPane.ERROR_MESSAGE);
      return false;
    }
    return true;
  } // writeFile

  /**
    * Convert histogram data to a byte array
    * for storage using a byte array stream.
    *
    * @param hist Histogram object containing data to be packed.
   **/
  public static ByteBuffer packHistogram (Histogram hist) {

    // The write methods can throw IOExceptions so must set up
    // to catch them
    try {

      // Need the length of the title
      int num_chars_title = hist.getTitle ().length ();

      // The length of the label
      int num_chars_label = hist.getXLabel ().length ();

      // And the bin array
      int [] bins = hist.getBins ();

      // Add up total buffer size. This include 3*4 = 12 for the
      // title, label and bin array sizes. Also,
      //   under + overflow ints plus upper + lower range doubles = 24
      int total_byte_size = 12 + num_chars_title*2 + num_chars_label*2 +
                            bins.length*4 + 24;

      ByteBuffer buffer = ByteBuffer.allocateDirect (total_byte_size);

      buffer.putInt (num_chars_title);
      CharBuffer char_buffer = CharBuffer.wrap (hist.getTitle ());
      (buffer.asCharBuffer ()).put (char_buffer);

      buffer.putInt (num_chars_label);
      char_buffer = CharBuffer.wrap (hist.getXLabel ());
      (buffer.asCharBuffer ()).put (char_buffer);

      buffer.putInt (bins.length);
      IntBuffer int_buffer = IntBuffer.wrap (bins);
      (buffer.asIntBuffer ()).put (int_buffer);

      // Save underflow value.
      buffer.putInt (hist.getValue (-1));
      // Save overflow value.
      buffer.putInt (hist.getValue (bins.length));

      // Write the lower and upper range values
      buffer.putDouble (hist.getLo ());
      buffer.putDouble (hist.getHi ());

      return buffer;

    }
    catch (BufferOverflowException e) {
      JOptionPane.showMessageDialog (
            null,
            "Error in packing data!!\n\r" + e,
            "Histogram Data Error",
            JOptionPane.ERROR_MESSAGE);
       return null;
    }
  } // packHistogram

  /** Re-build a histogram from a byte array. **/
  public static Histogram unpackHistogram (ByteBuffer hist_buffer){

    // The read  methods can throw IOExceptions so must set up
    // to catch them
    try {
      // First read the characters for the title
      int num_chars = hist_buffer.getInt ();
      char [] char_array = new char[num_chars];
      for (int i=0; i < num_chars; i++) {
        char_array[i] = hist_buffer.getChar ();
      }

      String title = String.valueOf (char_array);

      // First read the characters for the horizontal label
      num_chars = hist_buffer.getInt ();
      char_array = new char[num_chars];
      for (int i=0; i < num_chars; i++) {
        char_array[i] = hist_buffer.getChar ();
      }

      String x_label = String.valueOf (char_array);

      // Get the bin data
      int num_bins = hist_buffer.getInt ();
      int [] bins = new int[num_bins];
      for (int i=0; i < num_bins; i++)  {
          bins[i] = hist_buffer.getInt ();
      }

      int under_flows = hist_buffer.getInt ();
      int over_flows  = hist_buffer.getInt ();

      double lo = hist_buffer.getDouble ();
      double hi = hist_buffer.getDouble ();

      // Create a histogram with
      Histogram hist = new Histogram (title, x_label, num_bins, lo, hi);
      // Pack the rest of the data.
      hist.pack (bins, under_flows, over_flows, lo, hi);

      return hist;

    } catch (BufferUnderflowException e) {
       JOptionPane.showMessageDialog (
            null,
            "Error in unpacking data!!\n\r" + e,
            "Histogram Data Error",
            JOptionPane.ERROR_MESSAGE);
       return null;
    }
  } // unpackHistogram

     ... Rest of code is identical to that in HistIOTools.

} // class HistNIOTools

 

 

References & Web Resources

 

Most recent update: August 18, 2005

              Tech
Histogram I/O
Hist I/O - Get/Set
  Demo 1
Hist I/O - Objects
  Demo 2
HistogramStream
  Demo 3
Filtering Data
  Demo 4
Exercises

           Physics
Physics Model
Simulation Design
Physics Simulator
  Demo 1
Experiment Design
Experiment Sim.
  Demo 2
Analysis
Expt. + Analysis
  Demo 3
Exercises

  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.