August 30, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

FileChannel Objects in Java, Using View Objects for Different Types

  • October 29, 2002
  • By Richard G. Baldwin
  • Send Email »
  • More Articles »

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




Page 2 of 3



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel