|
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
-
-
java.nio
- describes the various buffer classes
-
- MappedByteBuffer
- a subclass of ByteBuffer
that we discuss in the FileChannel
section below.
-
Most recent update: August 18, 2005
|
|
|