Return-Path: <env_16600087-335761239@hermes.sun.com>
Received: from fort-point-station.mit.edu by po10.mit.edu (8.9.2/4.7) id UAA01968; Tue, 4 Jun 2002 20:44:39 -0400 (EDT)
Received: from hermes.sun.com (hermes.sun.com [64.124.140.169])
	by fort-point-station.mit.edu (8.9.2/8.9.2) with SMTP id UAA11196
	for <alexp@mit.edu>; Tue, 4 Jun 2002 20:44:39 -0400 (EDT)
Date: Tue, 4 Jun 2002 16:44:39 GMT-08:00
From: "JDC Editorial" <body_16600087-335761239@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <16600087-335761239@hermes.sun.com>
Subject: JDC Tech Tips
Mime-Version: 1.0
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: SunMail 1.0

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE>
Technical Tips
</TITLE>
</HEAD>

<body bgcolor="#ffffff">
<a name="top"></a>
<table border="0" cellpadding="0" cellspacing="0" width="640">
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>

<tr>
<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>

<td>
<table border="0" cellpadding="0" cellspacing="0" width="640">
<tr>
<td colspan="2">
<img src="http://developer.java.sun.com/images/jdc_techtips_header.gif" width="640" alt="" border="0"></td>
</tr>

<tr>
<td colspan="2" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>

<!-- ================== -->
<!-- Start Main Content -->
<!-- ================== -->

<tr bgcolor="#59588d">
<td height="20">&nbsp;&nbsp;&nbsp;<a href="http://developer.java.sun.com/developer/TechTips/txtarchive/2002/June02_GlenM.txt?s=06&w=23" style="text-decoration:none;"><font face="Verdana" size="2" color="ffffff">View this issue as simple text</font></a></td>
<td align="right" height="20"><font face="Verdana" size="2" color="ffffff"><b>June 4, 2002</b></font>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</td>
</tr>
<tr>
<td colspan="2" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>

<tr><td colspan="2">

<table border="0" cellpadding="10" cellspacing="0" width="640">
<tr><td>

<FORM METHOD="GET" ACTION="http://search.java.sun.com/search/java/?s=06&w=23">
<table BORDER="0" CELLPADDING="0" CELLSPACING="0" WIDTH="100%">
<tr>
<td>
        
<table BORDER="0" CELLPADDING="0" CELLSPACING="0">
<TR> 
<td  align="left" VALIGN="middle"><img src="http://developer.java.sun.com/images/issue.gif" border="0" alt=""></td>
              
<td VALIGN="middle" align="right" WIDTH="100%">
<FONT SIZE="2">
<INPUT TYPE="text" SIZE="15" MAXLENGTH="128" NAME=qt></FONT></td>
            
<td VALIGN="middle" WIDTH="55" align="right">
<INPUT TYPE="image" SRC="http://developer.java.sun.com/images/search.button.gif" ALT="Search" value="search" BORDER="0" WIDTH="55"></td>
</tr>
</table>
</td></tr>
</table>
</FORM>

<p>
<a href="#1"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=""><font face="Verdana" size="2" color="#666699">Using the <code>CharSequence</code> Interface</font></a>
<br>    
<a href="#2"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=""><font face="Verdana" size="2" color="#666699">Programming With Buffers</font></a>
</p>

<p>
<font face="Verdana" size="2" color="#000000">These tips were developed using java<font size="-2"><sup>TM</sup></font> 2 SDK, Standard Edition, v 1.4.</font>
</p>

<p>
<font face="Verdana" size="2" color="#000000">This issue of the JDC Tech Tips is written by Glen McCluskey.</font>
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="1"></a>
<p>
<font face="Verdana" size="3"><b>Using the <code>CharSequence</code> Interface</b></font>
</p>


<p>
<font face="Verdana" size="2" color="#000000">
Suppose that you're writing a method in the Java programming language. Suppose too that you want to specify one of the method parameters such that a user of the method can pass a <code>string</code> or sequence of characters to the method. An obvious way to do this is to use a <code>String</code> parameter. But what happens if the method caller has a <code>StringBuffer</code> or <code>CharBuffer</code> object instead of a <code>String</code>? Or what happens if the caller wants to pass a character array to your method? In those cases, using a <code>String</code> parameter will not work. Instead, you can use the <code>java.lang.CharSequence</code> interface. This is an interface that supports generalization of character sequences.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
A class that implements the <code>CharSequence</code> interface must define the following methods:</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
<code>length</code> - returns the number of characters in the sequence
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
<code>charAt</code> - returns a character at a given position
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
<code>subSequence</code> - returns a subsequence of a sequence
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
<code>toString</code> - returns a String containing the sequence characters
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
The <code>String</code>, <code>StringBuffer</code>, and <code>CharBuffer</code> classes implement the <code>CharSequence</code> interface, so passing an object of one of these classes to a method with a <code>CharSequence</code> parameter will work. Let's look at an example:
</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    import java.nio.*;
    
    public class CSDemo1 {
    
        // dump out information about a CharSequence
    
        public static void dumpSeq(CharSequence cs) {
            System.out.println(
                            &quot;length = &quot; + cs.length());
            System.out.println(
                       &quot;first char = &quot; + cs.charAt(0));
            System.out.println(&quot;string = &quot; + cs);
            System.out.println();
        }
   
        public static void main(String args[]) {
    
            // String
    
            String s = &quot;test&quot;;
            dumpSeq(s);
    
            // StringBuffer
    
            StringBuffer sb = new StringBuffer(&quot;ing&quot;);
            dumpSeq(sb);
    
            // CharBuffer
    
            CharBuffer cb = CharBuffer.allocate(3);
            cb.put(&quot;123&quot;);
            cb.rewind();
            dumpSeq(cb);
        }
    } 
</pre>
</font>



<p><font face="Verdana" size="2" color="#000000">
In the <code>CSDemo1</code> program, <code>dumpSeq</code> is a method with a <code>CharSequence</code> parameter. The parameter is passed instances of <code>String</code>, <code>StringBuffer</code>, and <code>CharBuffer</code>. When you run the program, the output is:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    length = 4
    first char = t
    string = test

    length = 3
    first char = i
    string = ing

    length = 3
    first char = 1
    string = 123 
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
This example makes clear that you can use <code>CharSequence</code> as a generalization of character sequences. It shows that you can write methods that accept objects of any class type that implements the <code>CharSequence</code> interface.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Let's look at another example, one that defines a <code>CharArrayWrapper</code> class that implements the <code>CharSequence</code> interface. The class is used to wrap a character array such that the wrapper object can be passed as an argument to a method expecting a <code>CharSequence</code>. Here's what the code looks like:</font>
</p>



<font face="Verdana" size="2" color="#000000">
<pre>
    class CharArrayWrapper implements CharSequence {
        private char vec[];
        private int off;
        private int len;
    
        // length of sequence
    
        public int length() {
            return len;
        }
    
        // character at a given index
    
        public char charAt(int index) {
            if (index &lt; 0 || index >= len) {
                throw new IndexOutOfBoundsException(
                    &quot;invalid index&quot;);
            }
            return vec[index];
        }
    
        // subsequence from start (inclusive) 
        // to end (exclusive)
    
        public CharSequence subSequence(
                                  int start, int end) {
            if (start &lt; 0 || end &lt; 0 || end &gt; len || 
                                         start &gt; end) {
                throw new IndexOutOfBoundsException(
                    &quot;invalid start/end&quot;);
            }
            return new CharArrayWrapper(
                              vec, start, end - start);
        }
    
        // convert to string
    
        public String toString() {
            return new String(vec, off, len);
        }
    
        // construct an CharArrayWrapper
        // from a portion of a char array 
    
        public CharArrayWrapper(
                        char vec[], int off, int len) {
            if (vec == null) {
                throw new NullPointerException(
                                      &quot;null vec&quot;);
            }
            if (off &lt; 0 || len &lt; 0 || 
                              off &gt; vec.length - len) {
                throw new IllegalArgumentException(
                                        &quot;bad off/len&quot;);
            }
            this.vec = vec;
            this.off = off;
            this.len = len;
        }
   
        // construct a CharArrayWrapper 
        // from a char array
    
        public CharArrayWrapper(char vec[]) {
            this(vec, 0, vec.length);
        }
    }
    
    public class CSDemo2 {
        public static void main(String args[]) {
    
            // create array and wrap it
    
            char vec[] = {'a', 'b', 'c', 'd', 'e'};
            CharSequence cs = 
                             new CharArrayWrapper(vec);
    
            // test the CharArrayWrapper 
            // interface implementation
    
            System.out.println(&quot;string = &quot; + cs);
            System.out.println(
                            &quot;length = &quot; + cs.length());
            System.out.println(&quot;subSequence(2,4) = &quot; +
                cs.subSequence(2, 4));
            System.out.println(
                        &quot;charAt(0) = &quot; + cs.charAt(0));
        }
    }
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
In the <code>CSDemo2</code> program, the <code>subSequence</code> method is implemented by creating another <code>CharArrayWrapper</code> object, one that has a view of a portion of the original character array. The <code>toString</code> method is implemented by calling a <code>String</code> constructor with the array as its argument. Note that creating a <code>string</code> in this way is fairly expensive, because the array is copied. If instead, you simply provide a <code>CharArrayWrapper</code> for an array, it involves no copying.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
The <code>CharArrayWrapper</code> class and <code>CharSequence</code> provide a read-only interface. There's no way to modify the character sequence using this interface. If you're familiar with the <code>java.nio.CharBuffer</code> class, you'll notice that using that class to wrap a character array achieves a similar effect to <code>CharArrayWrapper</code>. That's because <code>CharBuffer</code> implements the <code>CharSequence</code> interface. The <code>CharArrayWrapper</code> class and <code>CharSequence</code> provide a read-only interface. There's no way to modify the character sequence using this interface. If you're familiar with the <code>java.nio.CharBuffer</code> class, you'll notice that using that class to wrap a character array achieves a similar effect to <code>CharArrayWrapper</code>. That's because <code>CharBuffer</code> implements the <code>CharSequence</code> interface.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
If you run the <code>CSDemo2</code> program, the results look like this:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    string = abcde
    length = 5
    subSequence(2,4) = cd
    charAt(0) = a 
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The <code>CharSequence</code> interface is used in the regular expression package (<code>java.util.regex</code>). You can see an example of its use by examining the <code>BufferDemo7</code> program in the Programming With Buffers tip that follows this tip.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
For more information about the <code>CharSequence</code> interface, see the <a href="http://java.sun.com/j2se/1.4/docs/api/java/lang/CharSequence.html?s=06&w=23"><font face="Verdana" size="2" color="#666699">interface description</font></a>.</font>
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top"><font face="Verdana" size="2" color="#666699">back to top</font><img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt=""></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="2"></a>
<p>
<font face="Verdana" size="3"><b>Programming With Buffers</b></font>
</p>

<p>
<font face="Verdana" size="2" color="#000000">
If you've done any I/O programming in the Java programming language, you've probably had a situation where you're reading from an input stream into an array, and then writing the array contents to an output stream. Typically, you might have an array that's 1024 bytes long, and each read of the stream puts 0-to-1024 bytes into the array.</font>
</p>

<p>
<font face="Verdana" size="2" color="#000000">
An array used in this way is also called a buffer. Version 1.4 of the Java 2 Platform, Standard Edition adds a major new set of buffer classes. These classes are found in the <code>java.nio</code> package. The classes are based on the the superclass <code>java.nio.Buffer</code>. Formally, a buffer is a linear, finite sequence of elements of a specific primitive type such as char (<code>CharBuffer</code>) or double (<code>DoubleBuffer</code>). Buffers are typically used in I/O operations, but you can also use them in other areas.</font>
</p>

<p>
<font face="Verdana" size="2" color="#000000">
This tip examines some uses of buffers. Let's start by looking at an example that shows how buffers are allocated:</font>
</p>


<font face="Verdana" size="2" color="#000000">
<pre>
    import java.nio.*;
    
    public class BufferDemo1 {
        public static void main(String args[]) {
    
            // allocate non-direct buffer
    
            ByteBuffer bb1 = ByteBuffer.allocate(100);
            System.out.println(bb1);
    
            // allocate direct buffer
    
            ByteBuffer bb2 = 
                        ByteBuffer.allocateDirect(100);
            System.out.println(bb2);
        }
    }
</pre>
</font>


<p>
<font face="Verdana" size="2" color="#000000">
Buffers have a fixed size, in this example 100 bytes. Here, the program allocates one buffer as a direct buffer, and another as non-direct. What does this mean? The documentation for <a href="http://java.sun.com/j2se/1.4/docs/api/java/nio/ByteBuffer.html?s=06&w=23"><code><font face="Verdana" size="2" color="#666699">ByteBuffer</font></code></a> explains it this way:</font>
</p>

<blockquote>
<p><font face="Verdana" size="2" color="#000000">
A byte buffer is either direct or non-direct. Given a direct byte buffer, the Java virtual machine<a href="#JVM"><font face="Verdana" size="2" color="#666699">*</font></a> will make a best effort to perform native I/O operations directly upon it. That is, it will attempt to avoid copying the buffer's content to (or from) an intermediate buffer before (or after) each invocation of one of the underlying operating system's native I/O operations.</font>
</p>
</blockquote>

<p>
<font face="Verdana" size="2" color="#000000">
Direct buffers could have higher allocation costs, and they're not always the right choice. However, they are worth considering to improve the performance of I/O.
</font>
</p>

<p>
<font face="Verdana" size="2" color="#000000">
When you run the <code>BufferDemo1</code> program, the result is:
</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    java.nio.HeapByteBuffer[pos=0 lim=100 cap=100]
    java.nio.DirectByteBuffer[pos=0 lim=100 cap=100]
</pre>
</font>

<p>
<font face="Verdana" size="2" color="#000000">
<code>HeapByteBuffer</code> and <code>DirectByteBuffer</code> are internal classes used in the implementation of <code>ByteBuffer</code>.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
You might wonder what the <code>pos</code>, <code>lim</code>, and <code>cap</code> values represent in the result. These are basic properties of a buffer. They represent the position, limit, and capacity of the buffer, respectively. A buffer's position is the index (0 basis) of the next element to be read or written. A buffer's limit is the index of the next element that should not be read or written. (The difference between the limit and the position is a buffer's &quot;remaining value,&quot; that is, the number of elements remaining in the buffer.) A buffer's capacity is its fixed number of elements. In the <code>BufferDemo1</code> example, the capacity is 100 elements, and each element is a single byte.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
These basic properties of a buffer represent one answer to the question &quot;how does a buffer differ from an array of the same primitive type?&quot; A buffer is essentially a wrapper on top of an array. It contains additional state information about the use of the array, for example, the index of the next location to be read or written.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Let's solidify these concepts with another example:
</font>
</p>


<font face="Verdana" size="2" color="#000000">
<pre>
    import java.nio.*;
    
    public class BufferDemo2 {
    
        // dump state of a buffer
    
        static void dumpState(Buffer b) {
            System.out.println(
                           &quot;position=&quot; + b.position());
            System.out.println(&quot;limit=&quot; + b.limit());
            System.out.println(
                           &quot;capacity=&quot; + b.capacity());
            System.out.println(
                         &quot;remaining=&quot; + b.remaining());
            System.out.println();
        }
    
        public static void main(String args[]) {
    
            // allocate buffer
    
            IntBuffer ib = IntBuffer.allocate(2);
            dumpState(ib);
    
            // add a value to it
    
            ib.put(37);
            dumpState(ib);
    
            // add another value to it
    
            ib.put(47);
            dumpState(ib);
        }
    }
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The <code>BufferDemo2</code> program allocates a two-long int buffer. It then adds two values to the buffer using relative put operations. These operations are relative to the current position in the buffer. Each time the program adds an element, the position is incremented, and the number of remaining elements decreases by one. If you run the program, the output looks like this:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    position=0
    limit=2
    capacity=2
    remaining=2
    
    position=1
    limit=2
    capacity=2
    remaining=1
    
    position=2
    limit=2
    capacity=2
    remaining=0
</pre>
</font>


<p><font face="Verdana" size="2" color="#000000">
Let's look at a more complicated example. It's another example of using buffers for I/O -- here buffers are used to copy one file to another. However, the example has a couple of unusual aspects to it. First, the input and output &quot;files&quot; are byte arrays. Second, the example simulates a case where I/O doesn't work very well, that is, the case where an I/O request is only partially successful. For example, in this case, you might request that two bytes be read from a file, but zero, one, or two bytes might actually be read.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Here's the code:</font>
</p>


<font face="Verdana" size="2" color="#000000">
<pre>
    import java.nio.ByteBuffer;
    import java.util.Random;
    
    public class BufferDemo3 {
        static Random rn = new Random(0);
        
        // size of input &quot;file&quot; (buffer)
    
        static final int FILESIZE = 10;
    
        // input and output &quot;files&quot; (arrays of bytes)
    
        static byte infile[] = new byte[FILESIZE];
        static int inptr = 0;
        static byte outfile[] = new byte[FILESIZE];
        static int outptr = 0;
    
        // initialize input
    
        static {
            for (int i = 0; i &lt; infile.length; i++) {
                infile[i] = (byte)(i + 1);
            }
        }
    
        // read 0-2 bytes from input file
    
        static int read(ByteBuffer bb) {
    
            // at end of file?
    
            if (inptr == infile.length) {
                return -1;
            }
    
            // read 0-2 bytes from input 
            // and put into buffer
    
            int n = rn.nextInt(3);
            int cnt = 0;
            while (bb.hasRemaining() &amp;&amp; n &gt; 0 &amp;&amp;
            inptr < infile.length) {
                bb.put(infile[inptr++]);
                cnt++;
                n--;
            }
    
            // return the amount read
    
            return cnt;
        }
    
        // write to output file
    
        static int write(ByteBuffer bb) {
    
            // read 0-2 bytes from buffer 
            // and add to output
    
            int n = rn.nextInt(3);
            int cnt = 0;
            while (bb.hasRemaining() &amp;&amp; n &gt; 0) {
                outfile[outptr++] = bb.get();
                cnt++;
                n--;
            }
    
            // return amount written
    
            return cnt;
        }
    
        public static void main(String args[]) {
    
            // allocate buffer
    
            ByteBuffer bb = ByteBuffer.allocate(2);
            bb.clear();
    
            // transfer from input to output file,
            // using buffer as intermediary
    
            int cnt = 0;
            while (cnt &lt; FILESIZE) {
    
                // handle case where at end of file
                // but buffer not yet empty
    
                if (
                  read(bb) &lt; 0 &amp;&amp; bb.position() == 0) {
                    break;
                }
                bb.flip();
                cnt += write(bb);
    
                // handle case where write only
                // partially successful
    
                bb.compact();
            }
    
            // check results of copy
    
            for (int i = 0; i &lt; outfile.length; i++) {
                if (outfile[i] != i + 1) {
                    System.out.println(
                                     &quot;compare error&quot;);
                }
            }
        }
    }
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The main method of the <code>BufferDemo3</code> program allocates a two-long byte buffer, clears it, and then uses the buffer to copy from one file (byte array) to another. Clearing the buffer makes it ready for use by setting the limit to the capacity and the position to zero.
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Each time it calls the <code>read</code> method, the program transfers zero, one, or two bytes from the input into the buffer. Each <code>write</code> call transfers zero, one, or two bytes from the buffer into the output.
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Notice that for each copy iteration, the program reads from the input, flips the buffer, and writes to the output. What does it mean to flip the buffer? Flipping sets the buffer limit to the current position, and then sets the position to zero. What's the benefit of flipping? Consider that as you write into a buffer, its position keeps going up. At some point, when you're done writing, you want to read from that buffer. Flipping captures the position (the amount you've written), and then sets the position to zero. This allows you to read up to the limit.
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
The <code>read</code> and <code>write</code> methods have to be sensitive to the fact that the buffer they're passed might not be empty. That's why the <code>read</code> and <code>write</code> methods call the <code>hasRemaining</code> method. Also, the loop in the <code>main</code> method has to handle the case where an end of file has been reached, but the buffer is not yet empty. That's why the <code>main</code> method includes the test:
</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    if (read(bb) &lt; 0 &amp;&amp; bb.position() == 0)
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
If you omit the latter part of this test, the program will work most of the time, but it occasionally does an incorrect copy.</font>
</p>

<p>
<font face="Verdana" size="2" color="#000000">
The main loop also has to handle the case where a write is only partially successful. In this case, the buffer still contains data to be written after the write method returns. This situation is handled by the compact method. This method copies the bytes between the buffer's current position and its limit to the beginning of the buffer. If you omit the call to the compact method, the copy hangs.
</font>
</p>

<p>
<font face="Verdana" size="2" color="#000000">
Let's look at some additional buffer features. Suppose that you have a byte array containing the bytes 0x39 and 0x30. These bytes represent the quantity 12345 as a little-endian 16-bit value (least significant byte first). How can you extract the value from this byte array? Here's one way:
</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    import java.nio.*;
    
    public class BufferDemo4 {
    
        // byte value for the short value 12345 
        // (little-endian)
    
        static final byte buf[] = {0x39, 0x30};
    
        public static void main(String args[]) {
    
            // allocate buffer
    
            ByteBuffer bb = ByteBuffer.allocate(2);
    
            // add contents of buf to it
    
            bb.put(buf);
    
            // prepare buffer for reading
    
            bb.flip();
    
            // make read-only, change order to
            // little-endian, and create view
    
            ShortBuffer sb = bb.asReadOnlyBuffer().
                order(ByteOrder.LITTLE_ENDIAN).
                asShortBuffer();
    
            // dump out original two bytes
    
            System.out.println(Integer.toHexString(bb.get(0)));
            System.out.println(Integer.toHexString(bb.get(1)));
    
            // dump out original two bytes as a short
    
            System.out.println(bb.getShort());
    
            // dump out little-endian view of short
    
            System.out.println(sb.get());
        }
    }
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The <code>BufferDemo4</code> program creates a two-long buffer, and then does a bulk add of the byte array containing the two values.
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
The program then creates a read-only view of the buffer. Here, the ordering is changed from big-endian to little-endian. Finally, the program creates a short view of the buffer. This process is an example of &quot;invocation chaining.&quot; In invocation chaining, each method returns a buffer, such that method invocations can be chained together. The net result of this operation is a view of the byte buffer as a sequence of read-only short values. Each value is composed of two bytes, with the bytes of each short assumed to be in little-endian order.
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
The original two bytes are dumped out using absolute <code>get</code> methods that do not affect the buffer position. Then the short value is displayed from the original buffer (which defaults to big-endian order). Last, the short value is displayed from the short view buffer, using little-endian order. The result is:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    39
    30
    14640
    12345
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The short values are different because two different byte orderings are applied. In other words, the byte values <code>0x39</code> and <code>0x30</code> have the value <code>14640</code> if viewed as a big-endian short. They have the the value <code>12345</code> if viewed as a little-endian short.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
The buffer classes include two methods, <code>duplicate</code> and <code>slice</code>, that you can use to create copies of buffers. These methods make shallow copies, that is, they copy only state information, and share the underlying buffer contents. Changes to the contents of one buffer is visible in a copy. The <code>duplicate</code> method copies the capacity, limit, and position values of a buffer. The <code>slice</code> method sets the position to zero, and the limit and capacity to the number of elements remaining in the original buffer. Let's look at an example of how <code>duplicate</code> and <code>slice</code> work:
</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    import java.nio.*;
    
    public class BufferDemo5 {
        public static void main(String args[]) {
    
            // allocate a buffer and add values to it
    
            IntBuffer ib = IntBuffer.allocate(2);
            ib.put(37);
            ib.put(47);
    
            // create duplicate and slice of buffer
    
            ib.position(1);
            IntBuffer dup = ib.duplicate();
            IntBuffer slc = ib.slice();
    
            // display buffer details
    
            System.out.println(dup);
            System.out.println(slc);
    
            // change index 0 of duplicate and then
            // display value of original
    
            dup.put(0, 57);
            System.out.println(ib.get(0));
        }
    }
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
If you run this program, the result is:
</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    java.nio.HeapIntBuffer[pos=1 lim=2 cap=2]
    java.nio.HeapIntBuffer[pos=0 lim=1 cap=1]
    57
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The first line of output is the duplicate of the original buffer. The duplicate contains the same position, limit, and capacity as the original. The second line of output is the slice of the original. The position was set to 1 when the slice was created. So the slice buffer has a smaller limit and capacity, and contains a view of only the last element of the original buffer.
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
The last output line illustrates the idea that changes to the duplicate are reflected in the original. When the value at index 0 in the duplicate is changed, the original buffer is changed as well. That's because the original and the duplicate share the same contents.
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
A final example illustrates the use of <code>MappedByteBuffer</code>, a subclass of <code>ByteBuffer</code>. Use a <code>MappedByteBuffer</code> to map a region of a file to a buffer. A <code>MappedByteBuffer</code> was used in the May 7, 2002 Tech Tip &quot;<a href="http://java.sun.com/jdc/JDCTechTips/2002/tt0507.html#tip1?s=06&w=23"><font face="Verdana" size="2" color="#666699">File Channels</font></a>&quot;.
</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Recall that the earlier Tech Tip in this issue, &quot;Using the <code>CharSequence</code> Interface,&quot; showed how to implement the <code>CharSequence</code> interface in an array wrapper class. Here's another example of implementing <code>CharSequence</code>, this time with the character sequence in a file.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Suppose you have the following program:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    import java.io.*;
    
    public class BufferDemo6 {
        public static void main(String args[]) 
                                   throws IOException {
    
            // write &quot;testing&quot; as a string to the 
            // output file, each char encoded as 
            // two bytes
    
            FileOutputStream fos = 
                          new FileOutputStream(&quot;data&quot;);
            DataOutputStream dos = 
                             new DataOutputStream(fos);
            dos.writeChars(&quot;testing&quot;);
            dos.close();
            fos.close();
        }
    }
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The <code>BufferDemo6</code> program writes the string &quot;testing&quot; to a file, with each Unicode character written as two bytes.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
What if you could make the contents of this file &quot;implement&quot; the <code>CharSequence</code> interface, so that the contents could be passed to a method that expects a <code>CharSequence</code> parameter? Is there any way to do this? Here's one approach, that amends the <code>CSDemo1</code> program example from the Tech Tip &quot;Using the <code>CharSequence</code> Interface&quot;:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    import java.io.*;
    import java.nio.*;
    import java.nio.channels.*;
    
    public class BufferDemo7 {
    
        // dump out information about a CharSequence
    
        public static void dumpSeq(CharSequence cs) {
            System.out.println(
                            &quot;length = &quot; + cs.length());
            System.out.println(
                       &quot;first char = &quot; + cs.charAt(0));
            System.out.println(&quot;string = &quot; + cs);
            System.out.println();
        }

        public static void main(String args[]) 
                                   throws IOException {
    
            // String
    
            String s = &quot;test&quot;;
            dumpSeq(s);
    
            // StringBuffer
    
            StringBuffer sb = new StringBuffer(&quot;ing&quot;);
            dumpSeq(sb);
    
            // CharBuffer
    
            CharBuffer cb = CharBuffer.allocate(3);
            cb.put(&quot;123&quot;);
            cb.rewind();
            dumpSeq(cb);
    
            // mapped file
        
            FileInputStream fis = 
                           new FileInputStream(&quot;data&quot;);
            FileChannel fc = fis.getChannel();
            MappedByteBuffer mbb =
                fc.map(FileChannel.MapMode.READ_ONLY, 
                                         0, fc.size());
            cb = mbb.asCharBuffer();
            dumpSeq(cb);
            fc.close();
            fis.close();
        }
    }
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
The first part of the <code>BufferDemo7</code> program is the same as the <code>CSDemo1</code> program. The difference is the last part of <code>BufferDemo7</code>. In that part, the program opens the data file written by <code>BufferDemo6</code>, gets a channel, and then maps the file contents to a <code>MappedByteBuffer</code>. It then creates a <code>CharBuffer</code> view of the <code>MappedByteBuffer</code>.</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
Because <code>CharBuffer</code> implements the <code>CharSequence</code> interface, the <code>CharBuffer</code> object can be passed to the <code>dumpSeq</code> method, and is treated just like a <code>String</code> or <code>StringBuffer</code>. The <code>CharBuffer</code> view in this case represents a region of a file. So accessing characters through the <code>CharSequence</code> interface means that characters are being read from a file.
</font></p>

<p><font face="Verdana" size="2" color="#000000">
If you run the <code>BufferDemo7</code> program, the output looks like this:</font>
</p>

<font face="Verdana" size="2" color="#000000">
<pre>
    length = 4
    first char = t
    string = test

    length = 3
    first char = i
    string = ing

    length = 3
    first char = 1
    string = 123

    length = 7
    first char = t
    string = testing
</pre>
</font>

<p><font face="Verdana" size="2" color="#000000">
For more information about programming with buffers, see the &quot;<a href="http://developer.java.sun.com/developer/technicalArticles/releases/nio/?s=06&w=23"><font face="Verdana" size="2" color="#666699">New I/0 Functionality for Java 2 Standard Edition 1.4</font></a>&quot;</font>
</p>

<p><font face="Verdana" size="2" color="#000000">
<a name="JVM">&#42;</a> As used in this document, the terms &quot;Java 
virtual machine&quot; or &quot;JVM&quot; mean a virtual machine for the Java platform.</font>
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top"><font face="Verdana" size="2" color="#666699">back to top</font><img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt=""></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" ALT="Pixel" border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<p>
<font face="Verdana" color="#999999" size="2">IMPORTANT: Please read our Terms of Use, Privacy, and Licensing
policies:</font><br>
<a href="http://www.sun.com/share/text/termsofuse.html?s=06&w=23"><font face="Verdana" size="2" color="#666699">http://www.sun.com/share/text/termsofuse.html</font></a><br>
<a href="http://www.sun.com/privacy/?s=06&w=23"><font face="Verdana" size="2" color="#666699">http://www.sun.com/privacy/</font></a><br>
<a href="http://developer.java.sun.com/berkeley_license.html?s=06&w=23"><font face="Verdana" size="2" color="#666699">http://developer.java.sun.com/berkeley_license.html</font></a>
</p>

<P>
<font face="Verdana" color="#999999" size="2">Comments? Send your feedback on the Java<font size="-2"><sup>TM</sup></font> Developer Technical Tips to: <a href="mailto:jdc-webmaster@sun.com"><font face="Verdana" size="2" color="#666699">jdc-webmaster@sun.com</font></a></font>
</P>

<P>
<font face="Verdana" color="#999999" size="2">Go to the <a href="http://developer.java.sun.com/subscription/?s=06&w=23"><font face="Verdana" size="2" color="#666699">subscriptions page</font></a> to subscribe or unsubscribe to this newsletter.</font>
</P>

<p>
<font face="Verdana" color="#999999" size="2">ARCHIVES: You'll find the Java Developer Connection Technical Tips archives at:</font><br>
<a href="http://developer.java.sun.com/developer/JDCTechTips/?s=06&w=23"><font face="Verdana" size="2" color="#666699">http://developer.java.sun.com/developer/JDCTechTips/</font></a>
</p>

<P>
<font face="Verdana" color="#999999" size="2">Copyright 2001 <a href="http://www.sun.com?s=06&w=23"><font face="Verdana" size="2" color="#666699">Sun Microsystems, Inc.</font></a> All rights reserved. 901 San Antonio Road, Palo Alto, California 94303 USA.</font>
</P>


<P>
<font face="Verdana" color="#999999" size="2">Sun, Sun Microsystems, Java, Java Developer Connection, J2ME, JAIN, and PersonalJava are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.</font>
</P>

<!-- ================ -->
<!-- End Main Content -->
<!-- ================ -->

<center>
<a href="http://www.sun.com?s=06&w=23"><img src="http://developer.java.sun.com/images/lgsun.gif" border="0" alt="Sun Microsystems, Inc."></a>
</center>

</td>
</tr>
</table>

</td></tr>
</table>
</td>

<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt=""></td>
</tr>
</table>


<br><br>
<table bgcolor = "#efefef"><tr><td><a href="http://bulkmail.sun.com/servlet/PreferenceServlet?action=change&pref_name=content-type&pref_value=text&id=16600087-335761239"> Please send me newsletters in text</a></td></tr>
<tr><td><a href="http://bulkmail.sun.com/unsubscribe?16600087-335761239"> Please unsubscribe me from this newsletter</a><br>
<img src="http://bulkmail2.sun.com/OTServlet?id=16600087-335761239" width=1 height=1></td></tr></table>
</body>
</html>		

