JavaFileChannel Objects in Java, Using View Objects for Different Types

FileChannel Objects in Java, Using View Objects for Different Types

Developer.com content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More.

Java Programming Notes # 1790


Preface

New features in SDK Version 1.4.0

The recently released JavaTM 2 SDK, Standard Edition Version 1.4 contains a
large number of new features, including the concept
of IO channels.  The first lesson in this miniseries, entitled

FileChannel Objects in Java, Background Information
, introduced you to the concept of channels from a read/write IO viewpoint. 
The previous lesson, entitled

FileChannel Objects in Java, ByteBuffer Type
, showed you the basics of read/write
programming using channels.

Showing off the
advantages of channels

While the sample program in the previous
lesson illustrated the basics of using channels, it
didn’t do a very good job of showing off the advantages of channels.  The sample program in
this and subsequent lessons will do a
much better job of showing off the
advantages.

Different primitive types

In this lesson, I will show you how to use the FileChannel class, the
ByteBuffer
class, the DoubleBuffer class, and the ShortBuffer
class to transfer data of type
double and data of type short between the computer’s memory and a physical file.  You will
learn how to extend the concept to any primitive data type other than boolean. 

Mixed primitive types

In the next lesson, I will show you how to use the FileChannel class along
with the ByteBuffer class to create records consisting of sequences of
data values of mixed primitive types, and how to transfer those records
between the computer’s memory and a physical file.

Memory-mapped IO

Future lessons will teach you how to do memory-mapped IO using channels.

Viewing tip

You may find it useful to open another copy of this lesson in a separate
browser window.  That will make it easier for you to scroll back and
forth among the different listings and figures while you are reading about
them.

Supplementary material

I recommend that you also study the other lessons in my extensive collection
of online Java tutorials.  You will find those lessons published at
Gamelan.com
However, as of the date of this writing, Gamelan doesn’t maintain a consolidated
index of my Java tutorial lessons, and sometimes they are difficult to
locate there.  You will find a consolidated index at
www.DickBaldwin.com.

What is a FileChannel?

Sun describes an object of the FileChannel class simply as “A
channel for reading, writing, mapping, and manipulating a file.”

Discussion
and Sample Code

I will illustrate the FileChannel class using the sample program named
Channel02
.  You will find a complete listing
of the program in Listing 17 near the end of the lesson.  As is my normal
approach, I will discuss this program in fragments.


Writing and reading different primitive types

This program, which
was tested using Java SDK version 1.4.0 under Win2000, illustrates the use of
FileChannel
objects to write and read data of different primitive types from
a disk file.

Begin with type double

The program begins by first writing and then reading data of type
double using a DoubleBuffer view of a ByteBuffer object.

Applicable to primitive types other than boolean

Then the program illustrates that this approach is applicable to any primitive
type (other than boolean) by writing and then reading data of type
short
using a ShortBuffer view of a ByteBuffer object.

The main method

To keep things simple, the program consists of a main
method and several static convenience methods.  The beginning of the
main
method is shown in Listing 1.

  public static void main(
                        String[] args){
    ByteBuffer bBuf = 
        ByteBuffer.wrap(new byte[56]);

Listing 1

Wrap an array object in a ByteBuffer object

The code in Listing 1 uses the wrap method of the ByteBuffer
class to create a ByteBuffer object with a capacity of 56 bytes. 
Each byte in the buffer is initialized to a value of zero.  (This is not
new.  The methodology for creating ByteBuffer objects was discussed in
previous lessons.)

Create a DoubleBuffer view of the ByteBuffer object

The code in Listing 2 is new to this series of tutorial lessons, and is very
significant.  This code invokes the asDoubleBuffer method on
the ByteBuffer object’s reference to create a DoubleBuffer view
of the ByteBuffer object.

    DoubleBuffer dBuf = 
                 bBuf.asDoubleBuffer();

Listing 2

DoubleBuffer contents and properties

The content of the DoubleBuffer object starts at the ByteBuffer
object’s current position, (which is zero in this case).

The DoubleBuffer object’s position will be zero.  Its capacity and
its limit will be the number of bytes remaining in the ByteBuffer object
divided by eight.  Its mark will be undefined.  (The concept
of the bytes remaining in a ByteBuffer object was discussed in previous lessons.)

Important, changes will be visible …

It is very important to note that changes to
the ByteBuffer object’s content will be visible in the
DoubleBuffer
object and vice versa.

(Although I can’t tell you how the virtual machine manages this data from
a physical memory viewpoint, the effect is as if each of the two buffers simply provides a different
view of the same data.)

However, even though the two buffers appear to provide different views of the
same data, the two buffers’ position, limit,
and mark values will be independent of one another.

Also reflected in the original array object

Although it isn’t demonstrated in this program, changes to the original array
object’s contents will also be visible in the ByteBuffer object, and in
the DoubleBuffer object, and vice versa.  Thus, these two objects
simply provide different views of the data in the original array object. 
Stated differently, the original array object, the ByteBuffer object, and
the DoubleBuffer object all provide different views of the same data.

Units of type double

As you will see later, methods invoked on the DoubleBuffer object
operate in units of type double, and not in units of type byte
This makes it easy, for example, to iterate through the DoubleBuffer
object, accessing one double value during each iteration.

Populating the DoubleBuffer object

The code in Listing 3 uses the relative put method of the
DoubleBuffer
class to populate the DoubleBuffer object with six
double
values.  (Some of the values, such as 0.6666666666666666, were purposely designed to make
full use of the precision of the double type.)

    int cnt = 0;
    for(cnt = 0; cnt < 6; cnt++){
      dBuf.put((cnt+1.0)/3);
    }//end for loop

Listing 3

The relative put method

The relative put method writes the specified double value into
the buffer at the current position, and then increments the position by one.

(Several other overloaded versions of the put method are available,
including an absolute version that allows you to provide an index that specifies
the element into which the double value will be written.)

Prepare for writing to a disk file

At this point, I need to prepare the buffer for writing to a disk file. 
In particular, I need to set its limit to the number of values that I want to
have written to the file. 

The first statement in Listing 4 sets the limit of the
DoubleBuffer
object to the number of double values that I have
written into the buffer.

    dBuf.limit(cnt);
    bBuf.limit(dBuf.limit()*8);

Listing 4

Will actually write the ByteBuffer to the disk file

Actually, I’m not going to write the DoubleBuffer object to the disk
file.  Rather, I will use a FileChannel object to write the backing
ByteBuffer object to the disk file.

(FileChannel objects don’t deal directly with DoubleBuffer
objects, FloatBuffer objects, ShortBuffer objects, etc. 
Rather, they deal with the backing ByteBuffer object.)

What I really need to do …

Therefore, what I really need to do is set the limit on the ByteBuffer
object to correspond to the number of bytes consumed by the double values
written into the DoubleBuffer object.

After setting the limit on the DoubleBuffer object, the second
statement in
Listing 4 sets the limit on the backing ByteBuffer object to eight times
the limit of the DoubleBuffer object (remember, each double
value consists of eight bytes).

Display the DoubleBuffer data

The code in Listing 5 invokes the showDoubleBufferData method to
display the contents of the DoubleBuffer object.

    showDoubleBufferData(
                 dBuf,"dBuf-raw data");
                 
Listing 5

The showDoubleBufferData method

The entire showDoubleBufferData method is shown in Listing 6.

  static void showDoubleBufferData(
        DoubleBuffer buf, String name){
    //Displays buffer contents
    
    //Save position
    int pos = buf.position();
    //Set position to zero
    buf.position(0);
    System.out.println(
                   "Data for " + name);
    while(buf.hasRemaining()){
      System.out.println(buf.get());
    }//end while loop
    System.out.println();//new line
    //Restore position and return
    buf.position(pos);
  }//end showDoubleBufferData

Listing 6

Similar to a previous lesson

This method is essentially the same as a similar method that I explained in
the previous lesson.  The most significant difference is the
fact that the iterative loop (shown in boldface) iterates through the
object in eight-byte groups instead of iterating on individual bytes (as was the case in
the previous lesson).
 

Thus, each invocation of the relative get method retrieves an entire double
value (eight bytes) from the DoubleBuffer object, and then
increments the value of the position property of the DoubleBuffer object.

The output

The output produced by the code in Listing 6 is shown in Figure 1.

Data for dBuf-raw data
0.3333333333333333
0.6666666666666666
1.0
1.3333333333333333
1.6666666666666667
2.0

Figure 1

Hopefully this is what you expected to see for double data based on
division by three.

Return to the main method

Now, I’ll return the discussion to the flow of control in the main method.

Getting the size of a disk file

Later on, I’m going to write code to display the number of bytes in a disk
file.  I can do that by invoking the size method on a FileChannel
object.  I can also do that,
(independently of the FileChannel object)
by using a File
object that represents the file under investigation.

(In this lesson, I chose to take the independent
route and use a File object instead of invoking the size method on
the FileChannel object.)

Get and save an object of type File

The code in Listing 7 gets a File object that will represent a
physical file named junk.txt (when such a file comes into existence).

    String fileName = "junk.txt"; 
    File file = new File(fileName);

Listing 7

(As you may recall, a File object that represents a physical disk
file can provide information about the file that it represents, such as its
size, its location in the disk file structure, etc.  Note that the
use of the File object is not required for the proper operation of
this program, other than to make it easy to determine the size of the file.)

Local variables

The code in Listing 8 declares three local reference variables, which will be
used later.

    FileOutputStream oStr;
    FileInputStream iStr;
    FileChannel fileChan;

Listing 8

The variables declared in Listing 8 will be used later to hold references to
input and output file stream objects, as well as holding a reference to a
FileChannel
object.

Get FileChannel object for output

In the previous lesson, I showed you that the methodology for getting a
FileChannel
object (to be used for output only) is:

  • Get a FileOutputStream object.
  • Invoke the getChannel method on the FileOutputStream object.

The code in Listing 9 uses this methodology to get a FileChannel
object that can be used to transfer data from a ByteBuffer object to the
file named junk.txt.

    //Get FileChannel for output
    try{
      oStr = new FileOutputStream(
                             fileName);
      fileChan = oStr.getChannel();

Listing 9

Write the data to the disk file

The code in Listing 10 invokes the write method of the
FileChannel
class to write the output data from the ByteBuffer object
to the disk file.

      System.out.println(
               "Bytes written = " 
               + fileChan.write(bBuf));

      //Close stream and channel
      oStr.close();
      fileChan.close();

Listing 10

Important, also writes DoubleBuffer data to file

In the process of writing the data from the ByteBuffer object to the
disk file, the code in Listing 10 also writes the data from the DoubleBuffer
object to the disk file (remember, these are simply different views of the
same data).

Recap

The overall process implemented to this point in the program is:

  • Get a ByteBuffer object to serve as a backing buffer for a
    DoubleBuffer object.
  • Get a DoubleBuffer view of the ByteBuffer object (a
    DoubleBuffer
    object).
  • Manipulate the data in the DoubleBuffer object.
  • Write the contents of the ByteBuffer object (and hence the
    contents of the DoubleBuffer object)
    to the disk file.

Close the stream and the channel

The code in Listing 10 also closes the FileOutputStream object and the
FileChannel object.

Screen output

Note that the invocation of the write method in Listing 10 is in the
argument list of a println method.  The write method returns
the number of bytes written to the disk file, which is passed to the println
method.  Thus, the code in Listing
10 displays the number of bytes written to the disk file as shown in Figure 2.

Bytes written = 48

Figure 2

Six double values at eight bytes each equals …

Recall that six double values were stored in the DoubleBuffer
object.  Each double value requires eight bytes.  Therefore,
48 bytes were written to the disk file named junk.txt.

Get and display the size of the file

Recall the earlier discussion about using a File object that
represents the file named junk.txt to get and display the size of the
disk file.

      System.out.println(
                     "File length = " +
                        file.length());

Listing 11

The code in Listing 11 invokes the length method on the File
object to get and display the size of the file named junk.txt, producing
the output shown in Figure 3.

File length = 48

Figure 3

Happily, the size of the file in bytes matches the number of bytes reported
earlier as having been written to the file.

(Keep in mind, however, that from our viewpoint, the file really contains six values of type
double, each of which requires eight bytes.)

Clear the ByteBuffer object

The code in Listing 12 invokes the method named clearByteBufferData to
write a zero value in each element of the ByteBuffer object.

(I discussed this method in detail in the previous lesson, and won’t
repeat that discussion here.)

      clearByteBufferData(bBuf,"bBuf");

      showDoubleBufferData(
                          dBuf,"dBuf");


Listing 12

Changes made to the ByteBuffer …

Recall that changes made to the contents of the ByteBuffer object are reflected in
the DoubleBuffer object, and vice versa.  Therefore, setting the
individual element values to zero in the ByteBuffer object causes the elements in
the DoubleBuffer object to also be set to zero.

Display the DoubleBuffer data again

The code in Listing 12 also invokes the showDoubleBufferData method to
display the current contents of the DoubleBuffer object. 
The code in Listing 12 produces the output shown in Figure 4, which is probably
what you expected.

Clear bBuf
Data for dBuf
0.0
0.0
0.0
0.0
0.0
0.0

Figure 4

Why did I clear the ByteBuffer?

The main reason for first clearing and then displaying the contents of the
DoubleBuffer
object was to show that it no longer contains the six double
values written there earlier. 

The contents of the disk file will be read
into the DoubleBuffer object, overwriting the current contents of the
buffer.  Then the contents will be displayed again, showing that the data was
properly read from the disk file back into the buffer.

Get another FileChannel object

The code in Listing 13 uses the same methodology discussed earlier to get a
FileChannel
object suitable for reading the contents of the physical file
named junk.txt into the buffer.

      iStr = new FileInputStream(
                             fileName);
      fileChan = iStr.getChannel();


Listing 13

Read the file data into the buffer

The code in Listing 14 invokes the read method on the FileChannel
object to read the contents of the physical file into the ByteBuffer

      System.out.println(
                "Bytes read = " 
                + fileChan.read(bBuf));

      //Close stream and channel
      iStr.close();
      fileChan.close();
      //Display file length

      System.out.println(
                      "File length = " 
                      + file.length());


Listing 14

Then the stream and the channel are both closed.

The number of bytes read

The read method returns the number of bytes read, which is passed to
the println method for display.

Then the code in Listing 14 invokes the length method on the File
object to get and display the size of the physical file.  These operations
produce the output
shown in Figure 5.

Bytes read = 48
File length = 48

Figure 5

No surprise here

There should be no surprise that the number of bytes read is reported to be 48 bytes, since
that is the size of the file, as shown in Figure 5.

The double data is in the DoubleBuffer object

The read method in Listing 14 reads the contents in the disk file into
the ByteBuffer object (and hence into the DoubleBuffer object).

      showDoubleBufferData(
                          dBuf,"dBuf");
                          
Listing 15

Display the double data read from the disk file

The code in Listing 15 displays the contents of the DoubleBuffer object,
producing the output shown in Figure 6.

Data for dBuf
0.3333333333333333
0.6666666666666666
1.0
1.3333333333333333
1.6666666666666667
2.0

Figure 6

Again, no surprise

Happily, the current contents of the
DoubleBuffer
object are the same as the original contents that were written
to, and read back from the physical disk file.

What you have learned

Now you know how to use a DoubleBuffer object, in conjunction with a
backing ByteBuffer object to manipulate data of type double,
including writing the double data to a disk file and reading it back from
the disk file.

Classes for other primitive types

The following classes can be used in a similar fashion to manipulate all of
the primitive data types except boolean.

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

Repeat the process for data of type short

For purposes of illustration, the code in Listing 16 essentially repeats the
process shown above, using the ShortBuffer class in conjunction with the ByteBuffer class, to manipulate primitive data of type short.

Because of the similarity of this code to the code explained above, I won’t
discuss this code on a step-by-step basis.  However, the code does contain
numerous explanatory comments.

      clearByteBufferData(bBuf,"bBuf");
              
      //Get a DoubleBuffer view of the
      // ByteBuffer object
      ShortBuffer sBuf = 
                  bBuf.asShortBuffer();
      //Populate the ShortBuffer with
      // six short values.  Set its 
      // limit to the number of short
      // values stored there. Force the
      // limit of the ByteBuffer to 
      // track the limit of the 
      // ShortBuffer.
      // Note that it is necessary to 
      // take the number of bytes in a 
      // short into account when 
      // setting the limit on the 
      // ByteBuffer.

      for(cnt = 0; cnt < 6; cnt++){
        sBuf.put(
               (short)(32767/(cnt+1)));
      }//end for loop
      sBuf.limit(cnt);
      bBuf.limit(sBuf.limit()*2);

      //Display the data in the 
      // ShortBuffer
      showShortBufferData(
                 sBuf,"sBuf-raw data");
    
      //Get FileChannel for output
      oStr = new FileOutputStream(
                             fileName);
      fileChan = oStr.getChannel();

      //Write output data from the
      // ByteBuffer to the disk file.
      System.out.println(
               "Bytes written = " 
               + fileChan.write(bBuf));
      //Close stream and channel
      oStr.close();
      fileChan.close();
      //Display file length
      System.out.println(
                      "File length = " 
                      + file.length());

      //Clear the ByteBuffer, which in
      // turn will clear the 
      // ShortBuffer.
      clearByteBufferData(bBuf,"bBuf");

      //Display the ShortBuffer to 
      // confirm that it has been
      // cleared.
      showShortBufferData(
                          sBuf,"sBuf");

      //Get FileChannel for input
      iStr = new FileInputStream(
                             fileName);
      fileChan = iStr.getChannel();

      //Read data from disk file into
      // ByteBuffer.  Then display data
      // in the ShortBuffer.
      System.out.println(
                "Bytes read = " 
                + fileChan.read(bBuf));
      //Close stream and channel
      iStr.close();
      fileChan.close();
      //Display file length
      System.out.println(
                      "File length = " 
                      + file.length());

      //Display data
      showShortBufferData(sBuf,"sBuf");
      

Listing 16

The screen output

The code in Listing 16 produces the output shown in Figure 7.  You will
note that the output shown in Figure 7 is very similar to the output in the
previous figures, except that Figure 7 reflects data of type short
whereas
the previous figures reflect data of type double.

Clear bBuf
Data for sBuf-raw data
32767
16383
10922
8191
6553
5461

Bytes written = 12
File length = 12
Clear bBuf
Data for sBuf
0
0
0
0
0
0

Bytes read = 12
File length = 12
Data for sBuf
32767
16383
10922
8191
6553
5461

Figure 7

That’s it for now

By now you should understand a quite a lot about the use of the
FileChannel
class, the Buffer class, and the following view
classes:

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

Run the Program


If you haven’t already done so, I encourage you to copy the code from Listing
17 into your text editor, compile it, and execute it.  Experiment
with it, making changes, and observing the results of your changes.

Remember, however, that you must be running Java version 1.4.0 or later
to compile and execute this program.

Summary

In this lesson, I have shown you how to use the FileChannel class, the
ByteBuffer class, the DoubleBuffer class, and the ShortBuffer
class to transfer data of type double and data of type short
between the computer’s memory and a physical file. You have also learned how to
extend the concept to any primitive data type other than boolean.

You have learned how to create different primitive views of a ByteBuffer
object and how to manipulate the data in the buffer using the primitive views.

You have learned that changes made to the view objects are reflected in the
ByteBuffer object and vice versa.  You have also learned that those
changes are also reflected in the array object from which the ByteBuffer
object was created in the first place.

What’s Next?

In the next lesson, I will show you how to use the FileChannel class
along with the ByteBuffer class to create records consisting of sequences
of data values of mixed primitive types, and how to transfer those records
between the computer’s memory and a physical file.

In a lesson following that one, I will teach you how to do memory-mapped IO
using channels.

Future plans

As time goes on, I plan to publish additional lessons that will help
you learn to use other new IO features including:

  • File locks
  • Character-set encoders and decoders
  • Pattern matching on files using regular expressions
  • Socket channels for both clients and servers
  • Non-blocking reads
  • Non-blocking servers

Complete Program Listing


A complete listing of the program discussed in this lesson is shown in
Listing 17 below.

 

/* File Channel02.java
Copyright 2002, R.G.Baldwin
Revised 9/19/02

Illustrates use of FileChannel objects
to write and read data of different 
types from a disk file.

Writes and then reads data using a
DoubleBuffer view of a ByteBuffer.

Then writes and reads data using a
ShortBuffer view of a ByteBuffer.

Tested using JDK 1.4.0 under Win2000

The output is:

Data for dBuf-raw data
0.3333333333333333
0.6666666666666666
1.0
1.3333333333333333
1.6666666666666667
2.0

Bytes written = 48
File length = 48
Clear bBuf
Data for dBuf
0.0
0.0
0.0
0.0
0.0
0.0

Bytes read = 48
File length = 48
Data for dBuf
0.3333333333333333
0.6666666666666666
1.0
1.3333333333333333
1.6666666666666667
2.0

Clear bBuf
Data for sBuf-raw data
32767
16383
10922
8191
6553
5461

Bytes written = 12
File length = 12
Clear bBuf
Data for sBuf
0
0
0
0
0
0

Bytes read = 12
File length = 12
Data for sBuf
32767
16383
10922
8191
6553
5461

**************************************/

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

class Channel02{
  public static void main(
                        String[] args){
 
    //Create a ByteBuffer with a 
    // capacity of 56 bytes, and all
    // elements initialized to zero.
    ByteBuffer bBuf = 
        ByteBuffer.wrap(new byte[56]);
        
    //Get a DoubleBuffer view of the
    // ByteBuffer object
    DoubleBuffer dBuf = 
                 bBuf.asDoubleBuffer();
                                  
    //Populate the DoubleBuffer with
    // six double values.  Set its 
    // limit to the number of double
    // values stored there.  Force the
    // limit of the ByteBuffer to track
    // the limit of the DoubleBuffer.
    // Note that it is necessary to 
    // take the number of bytes in a 
    // double into account when setting
    // the limit on the ByteBuffer.
    int cnt = 0;
    for(cnt = 0; cnt < 6; cnt++){
      dBuf.put((cnt+1.0)/3);
    }//end for loop
    dBuf.limit(cnt);
    bBuf.limit(dBuf.limit()*8);

    //Display the data in the 
    // DoubleBuffer
    showDoubleBufferData(
                 dBuf,"dBuf-raw data");
                 
    //Get a File object to represent
    // a physical file.  Will use it
    // later to get the file length.
    String fileName = "junk.txt"; 
    File file = new File(fileName);
    
    //Declare variables for use later
    FileOutputStream oStr;
    FileInputStream iStr;
    FileChannel fileChan;

    //Get FileChannel for output
    try{
      oStr = new FileOutputStream(
                             fileName);
      fileChan = oStr.getChannel();

      //Write output data from the
      // ByteBuffer to the disk file.
      System.out.println(
               "Bytes written = " 
               + fileChan.write(bBuf));
      //Close stream and channel
      oStr.close();
      fileChan.close();
      //Display file length
      System.out.println(
                     "File length = " +
                        file.length());
      
      //Clear the ByteBuffer, which in
      // turn will clear the 
      // DoubleBuffer.
      clearByteBufferData(bBuf,"bBuf");

      //Display the DoubleBuffer to 
      // confirm that it has been
      // cleared.
      showDoubleBufferData(
                          dBuf,"dBuf");

      //Get FileChannel for input
      iStr = new FileInputStream(
                             fileName);
      fileChan = iStr.getChannel();

      //Read data from disk file into
      // ByteBuffer.  Then display data
      // in the DoubleBuffer.
      System.out.println(
                "Bytes read = " 
                + fileChan.read(bBuf));
      //Close stream and channel
      iStr.close();
      fileChan.close();
      //Display file length
      System.out.println(
                      "File length = " 
                      + file.length());

      //Display data
      showDoubleBufferData(
                          dBuf,"dBuf");
                          
      //Now repeat the process using 
      // the same ByteBuffer and the
      // same disk file, but using a
      // ShortBuffer view and 
      // populating the buffer with
      // primitive short data.
        
      clearByteBufferData(bBuf,"bBuf");
              
      //Get a DoubleBuffer view of the
      // ByteBuffer object
      ShortBuffer sBuf = 
                  bBuf.asShortBuffer();
      //Populate the ShortBuffer with
      // six short values.  Set its 
      // limit to the number of short
      // values stored there. Force the
      // limit of the ByteBuffer to 
      // track the limit of the 
      // ShortBuffer.
      // Note that it is necessary to 
      // take the number of bytes in a 
      // short into account when 
      // setting the limit on the 
      // ByteBuffer.

      for(cnt = 0; cnt < 6; cnt++){
        sBuf.put(
               (short)(32767/(cnt+1)));
      }//end for loop
      sBuf.limit(cnt);
      bBuf.limit(sBuf.limit()*2);

      //Display the data in the 
      // ShortBuffer
      showShortBufferData(
                 sBuf,"sBuf-raw data");
    
      //Get FileChannel for output
      oStr = new FileOutputStream(
                             fileName);
      fileChan = oStr.getChannel();

      //Write output data from the
      // ByteBuffer to the disk file.
      System.out.println(
               "Bytes written = " 
               + fileChan.write(bBuf));
      //Close stream and channel
      oStr.close();
      fileChan.close();
      //Display file length
      System.out.println(
                      "File length = " 
                      + file.length());

      //Clear the ByteBuffer, which in
      // turn will clear the 
      // ShortBuffer.
      clearByteBufferData(bBuf,"bBuf");

      //Display the ShortBuffer to 
      // confirm that it has been
      // cleared.
      showShortBufferData(
                          sBuf,"sBuf");

      //Get FileChannel for input
      iStr = new FileInputStream(
                             fileName);
      fileChan = iStr.getChannel();

      //Read data from disk file into
      // ByteBuffer.  Then display data
      // in the ShortBuffer.
      System.out.println(
                "Bytes read = " 
                + fileChan.read(bBuf));
      //Close stream and channel
      iStr.close();
      fileChan.close();
      //Display file length
      System.out.println(
                      "File length = " 
                      + file.length());

      //Display data
      showShortBufferData(sBuf,"sBuf");
      
    }catch(Exception e){
      System.out.println(e);}
  }// end main

  //---------------------------------//
  static void showDoubleBufferData(
        DoubleBuffer buf, String name){
    //Displays buffer contents
    
    //Save position
    int pos = buf.position();
    //Set position to zero
    buf.position(0);
    System.out.println(
                   "Data for " + name);
    while(buf.hasRemaining()){
      System.out.println(buf.get());
    }//end while loop
    System.out.println();//new line
    //Restore position and return
    buf.position(pos);
  }//end showDoubleBufferData
  //---------------------------------//

  static void showShortBufferData(
         ShortBuffer buf, String name){
    //Displays buffer contents
    
    //Save position
    int pos = buf.position();
    //Set position to zero
    buf.position(0);
    System.out.println(
                   "Data for " + name);
    while(buf.hasRemaining()){
      System.out.println(buf.get());
    }//end while loop
    System.out.println();//new line
    //Restore position and return
    buf.position(pos);
  }//end showShortBufferData
  //---------------------------------//
  
  static void clearByteBufferData(
          ByteBuffer buf, String name){
    //Stores 0 in each element of a
    // byte buffer.
    
    //Set position to zero
    buf.position(0);
    System.out.println(
                      "Clear " + name);
    while(buf.hasRemaining()){
      buf.put((byte)0);
    }//end while loop
    //Set position to zero and return
    buf.position(0);
  }//end clearByteBufferData
  //---------------------------------//
  
}//end class Channel02 definition

Listing 17

Copyright 2002, Richard G. Baldwin.  Reproduction in whole or in
part in any form or medium without express written permission from Richard
Baldwin is prohibited.

About the author

Richard Baldwin
is a college professor (at Austin Community College in Austin, TX) and
private consultant whose primary focus is a combination of Java, C#, and
XML. In addition to the many platform and/or language independent benefits
of Java and C# applications, he believes that a combination of Java, C#,
and XML will become the primary driving force in the delivery of structured
information on the Web.

Richard has participated in numerous consulting projects, and he
frequently provides onsite training at the high-tech companies located
in and around Austin, Texas.  He is the author of Baldwin’s Programming
Tutorials,
which has gained a worldwide following among experienced and aspiring programmers.
He has also published articles in JavaPro magazine.

Richard holds an MSEE degree from Southern Methodist University and
has many years of experience in the application of computer technology
to real-world problems.

Baldwin@DickBaldwin.com

-end-

 

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories