rev 5501 : imported patch io-trace

   1 /*
   2  * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.io;
  27 
  28 import java.nio.channels.FileChannel;
  29 import sun.nio.ch.FileChannelImpl;
  30 import sun.misc.IoTrace;
  31 
  32 
  33 /**
  34  * Instances of this class support both reading and writing to a
  35  * random access file. A random access file behaves like a large
  36  * array of bytes stored in the file system. There is a kind of cursor,
  37  * or index into the implied array, called the <em>file pointer</em>;
  38  * input operations read bytes starting at the file pointer and advance
  39  * the file pointer past the bytes read. If the random access file is
  40  * created in read/write mode, then output operations are also available;
  41  * output operations write bytes starting at the file pointer and advance
  42  * the file pointer past the bytes written. Output operations that write
  43  * past the current end of the implied array cause the array to be
  44  * extended. The file pointer can be read by the
  45  * <code>getFilePointer</code> method and set by the <code>seek</code>
  46  * method.
  47  * <p>
  48  * It is generally true of all the reading routines in this class that
  49  * if end-of-file is reached before the desired number of bytes has been
  50  * read, an <code>EOFException</code> (which is a kind of
  51  * <code>IOException</code>) is thrown. If any byte cannot be read for
  52  * any reason other than end-of-file, an <code>IOException</code> other
  53  * than <code>EOFException</code> is thrown. In particular, an
  54  * <code>IOException</code> may be thrown if the stream has been closed.
  55  *
  56  * @author  unascribed
  57  * @since   JDK1.0
  58  */
  59 
  60 public class RandomAccessFile implements DataOutput, DataInput, Closeable {
  61 
  62     private FileDescriptor fd;
  63     private FileChannel channel = null;
  64     private boolean rw;
  65 
  66     /* The path of the referenced file */
  67     private final String path;
  68 
  69     private Object closeLock = new Object();
  70     private volatile boolean closed = false;
  71 
  72     private static final int O_RDONLY = 1;
  73     private static final int O_RDWR =   2;
  74     private static final int O_SYNC =   4;
  75     private static final int O_DSYNC =  8;
  76 
  77     /**
  78      * Creates a random access file stream to read from, and optionally
  79      * to write to, a file with the specified name. A new
  80      * {@link FileDescriptor} object is created to represent the
  81      * connection to the file.
  82      *
  83      * <p> The <tt>mode</tt> argument specifies the access mode with which the
  84      * file is to be opened.  The permitted values and their meanings are as
  85      * specified for the <a
  86      * href="#mode"><tt>RandomAccessFile(File,String)</tt></a> constructor.
  87      *
  88      * <p>
  89      * If there is a security manager, its <code>checkRead</code> method
  90      * is called with the <code>name</code> argument
  91      * as its argument to see if read access to the file is allowed.
  92      * If the mode allows writing, the security manager's
  93      * <code>checkWrite</code> method
  94      * is also called with the <code>name</code> argument
  95      * as its argument to see if write access to the file is allowed.
  96      *
  97      * @param      name   the system-dependent filename
  98      * @param      mode   the access <a href="#mode">mode</a>
  99      * @exception  IllegalArgumentException  if the mode argument is not equal
 100      *               to one of <tt>"r"</tt>, <tt>"rw"</tt>, <tt>"rws"</tt>, or
 101      *               <tt>"rwd"</tt>
 102      * @exception FileNotFoundException
 103      *            if the mode is <tt>"r"</tt> but the given string does not
 104      *            denote an existing regular file, or if the mode begins with
 105      *            <tt>"rw"</tt> but the given string does not denote an
 106      *            existing, writable regular file and a new regular file of
 107      *            that name cannot be created, or if some other error occurs
 108      *            while opening or creating the file
 109      * @exception  SecurityException         if a security manager exists and its
 110      *               <code>checkRead</code> method denies read access to the file
 111      *               or the mode is "rw" and the security manager's
 112      *               <code>checkWrite</code> method denies write access to the file
 113      * @see        java.lang.SecurityException
 114      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
 115      * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 116      * @revised 1.4
 117      * @spec JSR-51
 118      */
 119     public RandomAccessFile(String name, String mode)
 120         throws FileNotFoundException
 121     {
 122         this(name != null ? new File(name) : null, mode);
 123     }
 124 
 125     /**
 126      * Creates a random access file stream to read from, and optionally to
 127      * write to, the file specified by the {@link File} argument.  A new {@link
 128      * FileDescriptor} object is created to represent this file connection.
 129      *
 130      * <a name="mode"><p> The <tt>mode</tt> argument specifies the access mode
 131      * in which the file is to be opened.  The permitted values and their
 132      * meanings are:
 133      *
 134      * <blockquote><table summary="Access mode permitted values and meanings">
 135      * <tr><th><p align="left">Value</p></th><th><p align="left">Meaning</p></th></tr>
 136      * <tr><td valign="top"><tt>"r"</tt></td>
 137      *     <td> Open for reading only.  Invoking any of the <tt>write</tt>
 138      *     methods of the resulting object will cause an {@link
 139      *     java.io.IOException} to be thrown. </td></tr>
 140      * <tr><td valign="top"><tt>"rw"</tt></td>
 141      *     <td> Open for reading and writing.  If the file does not already
 142      *     exist then an attempt will be made to create it. </td></tr>
 143      * <tr><td valign="top"><tt>"rws"</tt></td>
 144      *     <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
 145      *     require that every update to the file's content or metadata be
 146      *     written synchronously to the underlying storage device.  </td></tr>
 147      * <tr><td valign="top"><tt>"rwd"&nbsp;&nbsp;</tt></td>
 148      *     <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
 149      *     require that every update to the file's content be written
 150      *     synchronously to the underlying storage device. </td></tr>
 151      * </table></blockquote>
 152      *
 153      * The <tt>"rws"</tt> and <tt>"rwd"</tt> modes work much like the {@link
 154      * java.nio.channels.FileChannel#force(boolean) force(boolean)} method of
 155      * the {@link java.nio.channels.FileChannel} class, passing arguments of
 156      * <tt>true</tt> and <tt>false</tt>, respectively, except that they always
 157      * apply to every I/O operation and are therefore often more efficient.  If
 158      * the file resides on a local storage device then when an invocation of a
 159      * method of this class returns it is guaranteed that all changes made to
 160      * the file by that invocation will have been written to that device.  This
 161      * is useful for ensuring that critical information is not lost in the
 162      * event of a system crash.  If the file does not reside on a local device
 163      * then no such guarantee is made.
 164      *
 165      * <p> The <tt>"rwd"</tt> mode can be used to reduce the number of I/O
 166      * operations performed.  Using <tt>"rwd"</tt> only requires updates to the
 167      * file's content to be written to storage; using <tt>"rws"</tt> requires
 168      * updates to both the file's content and its metadata to be written, which
 169      * generally requires at least one more low-level I/O operation.
 170      *
 171      * <p> If there is a security manager, its <code>checkRead</code> method is
 172      * called with the pathname of the <code>file</code> argument as its
 173      * argument to see if read access to the file is allowed.  If the mode
 174      * allows writing, the security manager's <code>checkWrite</code> method is
 175      * also called with the path argument to see if write access to the file is
 176      * allowed.
 177      *
 178      * @param      file   the file object
 179      * @param      mode   the access mode, as described
 180      *                    <a href="#mode">above</a>
 181      * @exception  IllegalArgumentException  if the mode argument is not equal
 182      *               to one of <tt>"r"</tt>, <tt>"rw"</tt>, <tt>"rws"</tt>, or
 183      *               <tt>"rwd"</tt>
 184      * @exception FileNotFoundException
 185      *            if the mode is <tt>"r"</tt> but the given file object does
 186      *            not denote an existing regular file, or if the mode begins
 187      *            with <tt>"rw"</tt> but the given file object does not denote
 188      *            an existing, writable regular file and a new regular file of
 189      *            that name cannot be created, or if some other error occurs
 190      *            while opening or creating the file
 191      * @exception  SecurityException         if a security manager exists and its
 192      *               <code>checkRead</code> method denies read access to the file
 193      *               or the mode is "rw" and the security manager's
 194      *               <code>checkWrite</code> method denies write access to the file
 195      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
 196      * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
 197      * @see        java.nio.channels.FileChannel#force(boolean)
 198      * @revised 1.4
 199      * @spec JSR-51
 200      */
 201     public RandomAccessFile(File file, String mode)
 202         throws FileNotFoundException
 203     {
 204         String name = (file != null ? file.getPath() : null);
 205         int imode = -1;
 206         if (mode.equals("r"))
 207             imode = O_RDONLY;
 208         else if (mode.startsWith("rw")) {
 209             imode = O_RDWR;
 210             rw = true;
 211             if (mode.length() > 2) {
 212                 if (mode.equals("rws"))
 213                     imode |= O_SYNC;
 214                 else if (mode.equals("rwd"))
 215                     imode |= O_DSYNC;
 216                 else
 217                     imode = -1;
 218             }
 219         }
 220         if (imode < 0)
 221             throw new IllegalArgumentException("Illegal mode \"" + mode
 222                                                + "\" must be one of "
 223                                                + "\"r\", \"rw\", \"rws\","
 224                                                + " or \"rwd\"");
 225         SecurityManager security = System.getSecurityManager();
 226         if (security != null) {
 227             security.checkRead(name);
 228             if (rw) {
 229                 security.checkWrite(name);
 230             }
 231         }
 232         if (name == null) {
 233             throw new NullPointerException();
 234         }
 235         fd = new FileDescriptor();
 236         fd.incrementAndGetUseCount();
 237         this.path = name;
 238         open(name, imode);
 239     }
 240 
 241     /**
 242      * Returns the opaque file descriptor object associated with this
 243      * stream. </p>
 244      *
 245      * @return     the file descriptor object associated with this stream.
 246      * @exception  IOException  if an I/O error occurs.
 247      * @see        java.io.FileDescriptor
 248      */
 249     public final FileDescriptor getFD() throws IOException {
 250         if (fd != null) return fd;
 251         throw new IOException();
 252     }
 253 
 254     /**
 255      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 256      * object associated with this file.
 257      *
 258      * <p> The {@link java.nio.channels.FileChannel#position()
 259      * </code>position<code>} of the returned channel will always be equal to
 260      * this object's file-pointer offset as returned by the {@link
 261      * #getFilePointer getFilePointer} method.  Changing this object's
 262      * file-pointer offset, whether explicitly or by reading or writing bytes,
 263      * will change the position of the channel, and vice versa.  Changing the
 264      * file's length via this object will change the length seen via the file
 265      * channel, and vice versa.
 266      *
 267      * @return  the file channel associated with this file
 268      *
 269      * @since 1.4
 270      * @spec JSR-51
 271      */
 272     public final FileChannel getChannel() {
 273         synchronized (this) {
 274             if (channel == null) {
 275                 channel = FileChannelImpl.open(fd, path, true, rw, this);
 276 
 277                 /*
 278                  * FileDescriptor could be shared by FileInputStream or
 279                  * FileOutputStream.
 280                  * Ensure that FD is GC'ed only when all the streams/channels
 281                  * are done using it.
 282                  * Increment fd's use count. Invoking the channel's close()
 283                  * method will result in decrementing the use count set for
 284                  * the channel.
 285                  */
 286                 fd.incrementAndGetUseCount();
 287             }
 288             return channel;
 289         }
 290     }
 291 
 292     /**
 293      * Opens a file and returns the file descriptor.  The file is
 294      * opened in read-write mode if the O_RDWR bit in <code>mode</code>
 295      * is true, else the file is opened as read-only.
 296      * If the <code>name</code> refers to a directory, an IOException
 297      * is thrown.
 298      *
 299      * @param name the name of the file
 300      * @param mode the mode flags, a combination of the O_ constants
 301      *             defined above
 302      */
 303     private native void open(String name, int mode)
 304         throws FileNotFoundException;
 305 
 306     // 'Read' primitives
 307 
 308     /**
 309      * Reads a byte of data from this file. The byte is returned as an
 310      * integer in the range 0 to 255 (<code>0x00-0x0ff</code>). This
 311      * method blocks if no input is yet available.
 312      * <p>
 313      * Although <code>RandomAccessFile</code> is not a subclass of
 314      * <code>InputStream</code>, this method behaves in exactly the same
 315      * way as the {@link InputStream#read()} method of
 316      * <code>InputStream</code>.
 317      *
 318      * @return     the next byte of data, or <code>-1</code> if the end of the
 319      *             file has been reached.
 320      * @exception  IOException  if an I/O error occurs. Not thrown if
 321      *                          end-of-file has been reached.
 322      */
 323     public int read() throws IOException {
 324         Object traceContext = IoTrace.fileReadBegin(path);
 325         int b = 0;
 326         try {
 327             b = read0();
 328         } finally {
 329             IoTrace.fileReadEnd(traceContext, b == -1 ? 0 : 1);
 330         }
 331         return b;
 332     }
 333 
 334     private native int read0() throws IOException;
 335 
 336     /**
 337      * Reads a sub array as a sequence of bytes.
 338      * @param b the buffer into which the data is read.
 339      * @param off the start offset of the data.
 340      * @param len the number of bytes to read.
 341      * @exception IOException If an I/O error has occurred.
 342      */
 343     private int readBytes(byte b[], int off, int len) throws IOException {
 344         Object traceContext = IoTrace.fileReadBegin(path);
 345         int bytesRead = 0;
 346         try {
 347             bytesRead = readBytes0(b, off, len);
 348         } finally {
 349             IoTrace.fileReadEnd(traceContext, bytesRead == -1 ? 0 : bytesRead);
 350         }
 351         return bytesRead;
 352     }
 353 
 354     private native int readBytes0(byte b[], int off, int len) throws IOException;
 355 
 356     /**
 357      * Reads up to <code>len</code> bytes of data from this file into an
 358      * array of bytes. This method blocks until at least one byte of input
 359      * is available.
 360      * <p>
 361      * Although <code>RandomAccessFile</code> is not a subclass of
 362      * <code>InputStream</code>, this method behaves in exactly the
 363      * same way as the {@link InputStream#read(byte[], int, int)} method of
 364      * <code>InputStream</code>.
 365      *
 366      * @param      b     the buffer into which the data is read.
 367      * @param      off   the start offset in array <code>b</code>
 368      *                   at which the data is written.
 369      * @param      len   the maximum number of bytes read.
 370      * @return     the total number of bytes read into the buffer, or
 371      *             <code>-1</code> if there is no more data because the end of
 372      *             the file has been reached.
 373      * @exception  IOException If the first byte cannot be read for any reason
 374      * other than end of file, or if the random access file has been closed, or if
 375      * some other I/O error occurs.
 376      * @exception  NullPointerException If <code>b</code> is <code>null</code>.
 377      * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
 378      * <code>len</code> is negative, or <code>len</code> is greater than
 379      * <code>b.length - off</code>
 380      */
 381     public int read(byte b[], int off, int len) throws IOException {
 382         return readBytes(b, off, len);
 383     }
 384 
 385     /**
 386      * Reads up to <code>b.length</code> bytes of data from this file
 387      * into an array of bytes. This method blocks until at least one byte
 388      * of input is available.
 389      * <p>
 390      * Although <code>RandomAccessFile</code> is not a subclass of
 391      * <code>InputStream</code>, this method behaves in exactly the
 392      * same way as the {@link InputStream#read(byte[])} method of
 393      * <code>InputStream</code>.
 394      *
 395      * @param      b   the buffer into which the data is read.
 396      * @return     the total number of bytes read into the buffer, or
 397      *             <code>-1</code> if there is no more data because the end of
 398      *             this file has been reached.
 399      * @exception  IOException If the first byte cannot be read for any reason
 400      * other than end of file, or if the random access file has been closed, or if
 401      * some other I/O error occurs.
 402      * @exception  NullPointerException If <code>b</code> is <code>null</code>.
 403      */
 404     public int read(byte b[]) throws IOException {
 405         return readBytes(b, 0, b.length);
 406     }
 407 
 408     /**
 409      * Reads <code>b.length</code> bytes from this file into the byte
 410      * array, starting at the current file pointer. This method reads
 411      * repeatedly from the file until the requested number of bytes are
 412      * read. This method blocks until the requested number of bytes are
 413      * read, the end of the stream is detected, or an exception is thrown.
 414      *
 415      * @param      b   the buffer into which the data is read.
 416      * @exception  EOFException  if this file reaches the end before reading
 417      *               all the bytes.
 418      * @exception  IOException   if an I/O error occurs.
 419      */
 420     public final void readFully(byte b[]) throws IOException {
 421         readFully(b, 0, b.length);
 422     }
 423 
 424     /**
 425      * Reads exactly <code>len</code> bytes from this file into the byte
 426      * array, starting at the current file pointer. This method reads
 427      * repeatedly from the file until the requested number of bytes are
 428      * read. This method blocks until the requested number of bytes are
 429      * read, the end of the stream is detected, or an exception is thrown.
 430      *
 431      * @param      b     the buffer into which the data is read.
 432      * @param      off   the start offset of the data.
 433      * @param      len   the number of bytes to read.
 434      * @exception  EOFException  if this file reaches the end before reading
 435      *               all the bytes.
 436      * @exception  IOException   if an I/O error occurs.
 437      */
 438     public final void readFully(byte b[], int off, int len) throws IOException {
 439         int n = 0;
 440         do {
 441             int count = this.read(b, off + n, len - n);
 442             if (count < 0)
 443                 throw new EOFException();
 444             n += count;
 445         } while (n < len);
 446     }
 447 
 448     /**
 449      * Attempts to skip over <code>n</code> bytes of input discarding the
 450      * skipped bytes.
 451      * <p>
 452      *
 453      * This method may skip over some smaller number of bytes, possibly zero.
 454      * This may result from any of a number of conditions; reaching end of
 455      * file before <code>n</code> bytes have been skipped is only one
 456      * possibility. This method never throws an <code>EOFException</code>.
 457      * The actual number of bytes skipped is returned.  If <code>n</code>
 458      * is negative, no bytes are skipped.
 459      *
 460      * @param      n   the number of bytes to be skipped.
 461      * @return     the actual number of bytes skipped.
 462      * @exception  IOException  if an I/O error occurs.
 463      */
 464     public int skipBytes(int n) throws IOException {
 465         long pos;
 466         long len;
 467         long newpos;
 468 
 469         if (n <= 0) {
 470             return 0;
 471         }
 472         pos = getFilePointer();
 473         len = length();
 474         newpos = pos + n;
 475         if (newpos > len) {
 476             newpos = len;
 477         }
 478         seek(newpos);
 479 
 480         /* return the actual number of bytes skipped */
 481         return (int) (newpos - pos);
 482     }
 483 
 484     // 'Write' primitives
 485 
 486     /**
 487      * Writes the specified byte to this file. The write starts at
 488      * the current file pointer.
 489      *
 490      * @param      b   the <code>byte</code> to be written.
 491      * @exception  IOException  if an I/O error occurs.
 492      */
 493     public void write(int b) throws IOException {
 494         Object traceContext = IoTrace.fileWriteBegin(path);
 495         int bytesWritten = 0;
 496         try {
 497             write0(b);
 498             bytesWritten = 1;
 499         } finally {
 500             IoTrace.fileWriteEnd(traceContext, bytesWritten);
 501         }
 502     }
 503 
 504     private native void write0(int b) throws IOException;
 505 
 506     /**
 507      * Writes a sub array as a sequence of bytes.
 508      * @param b the data to be written

 509      * @param off the start offset in the data
 510      * @param len the number of bytes that are written
 511      * @exception IOException If an I/O error has occurred.
 512      */
 513     private void writeBytes(byte b[], int off, int len) throws IOException {
 514         Object traceContext = IoTrace.fileWriteBegin(path);
 515         int bytesWritten = 0;
 516         try {
 517             writeBytes0(b, off, len);
 518             bytesWritten = len;
 519         } finally {
 520             IoTrace.fileWriteEnd(traceContext, bytesWritten);
 521         }
 522     }
 523 
 524     private native void writeBytes0(byte b[], int off, int len) throws IOException;
 525 
 526     /**
 527      * Writes <code>b.length</code> bytes from the specified byte array
 528      * to this file, starting at the current file pointer.
 529      *
 530      * @param      b   the data.
 531      * @exception  IOException  if an I/O error occurs.
 532      */
 533     public void write(byte b[]) throws IOException {
 534         writeBytes(b, 0, b.length);
 535     }
 536 
 537     /**
 538      * Writes <code>len</code> bytes from the specified byte array
 539      * starting at offset <code>off</code> to this file.
 540      *
 541      * @param      b     the data.
 542      * @param      off   the start offset in the data.
 543      * @param      len   the number of bytes to write.
 544      * @exception  IOException  if an I/O error occurs.
 545      */
 546     public void write(byte b[], int off, int len) throws IOException {
 547         writeBytes(b, off, len);
 548     }
 549 
 550     // 'Random access' stuff
 551 
 552     /**
 553      * Returns the current offset in this file.
 554      *
 555      * @return     the offset from the beginning of the file, in bytes,
 556      *             at which the next read or write occurs.
 557      * @exception  IOException  if an I/O error occurs.
 558      */
 559     public native long getFilePointer() throws IOException;
 560 
 561     /**
 562      * Sets the file-pointer offset, measured from the beginning of this
 563      * file, at which the next read or write occurs.  The offset may be
 564      * set beyond the end of the file. Setting the offset beyond the end
 565      * of the file does not change the file length.  The file length will
 566      * change only by writing after the offset has been set beyond the end
 567      * of the file.
 568      *
 569      * @param      pos   the offset position, measured in bytes from the
 570      *                   beginning of the file, at which to set the file
 571      *                   pointer.
 572      * @exception  IOException  if <code>pos</code> is less than
 573      *                          <code>0</code> or if an I/O error occurs.
 574      */
 575     public native void seek(long pos) throws IOException;
 576 
 577     /**
 578      * Returns the length of this file.
 579      *
 580      * @return     the length of this file, measured in bytes.
 581      * @exception  IOException  if an I/O error occurs.
 582      */
 583     public native long length() throws IOException;
 584 
 585     /**
 586      * Sets the length of this file.
 587      *
 588      * <p> If the present length of the file as returned by the
 589      * <code>length</code> method is greater than the <code>newLength</code>
 590      * argument then the file will be truncated.  In this case, if the file
 591      * offset as returned by the <code>getFilePointer</code> method is greater
 592      * than <code>newLength</code> then after this method returns the offset
 593      * will be equal to <code>newLength</code>.
 594      *
 595      * <p> If the present length of the file as returned by the
 596      * <code>length</code> method is smaller than the <code>newLength</code>
 597      * argument then the file will be extended.  In this case, the contents of
 598      * the extended portion of the file are not defined.
 599      *
 600      * @param      newLength    The desired length of the file
 601      * @exception  IOException  If an I/O error occurs
 602      * @since      1.2
 603      */
 604     public native void setLength(long newLength) throws IOException;
 605 
 606     /**
 607      * Closes this random access file stream and releases any system
 608      * resources associated with the stream. A closed random access
 609      * file cannot perform input or output operations and cannot be
 610      * reopened.
 611      *
 612      * <p> If this file has an associated channel then the channel is closed
 613      * as well.
 614      *
 615      * @exception  IOException  if an I/O error occurs.
 616      *
 617      * @revised 1.4
 618      * @spec JSR-51
 619      */
 620     public void close() throws IOException {
 621         synchronized (closeLock) {
 622             if (closed) {
 623                 return;
 624             }
 625             closed = true;
 626         }
 627         if (channel != null) {
 628             /*
 629              * Decrement FD use count associated with the channel. The FD use
 630              * count is incremented whenever a new channel is obtained from
 631              * this stream.
 632              */
 633             fd.decrementAndGetUseCount();
 634             channel.close();
 635         }
 636 
 637         /*
 638          * Decrement FD use count associated with this stream.
 639          * The count got incremented by FileDescriptor during its construction.
 640          */
 641         fd.decrementAndGetUseCount();
 642         close0();
 643     }
 644 
 645     //
 646     //  Some "reading/writing Java data types" methods stolen from
 647     //  DataInputStream and DataOutputStream.
 648     //
 649 
 650     /**
 651      * Reads a <code>boolean</code> from this file. This method reads a
 652      * single byte from the file, starting at the current file pointer.
 653      * A value of <code>0</code> represents
 654      * <code>false</code>. Any other value represents <code>true</code>.
 655      * This method blocks until the byte is read, the end of the stream
 656      * is detected, or an exception is thrown.
 657      *
 658      * @return     the <code>boolean</code> value read.
 659      * @exception  EOFException  if this file has reached the end.
 660      * @exception  IOException   if an I/O error occurs.
 661      */
 662     public final boolean readBoolean() throws IOException {
 663         int ch = this.read();
 664         if (ch < 0)
 665             throw new EOFException();
 666         return (ch != 0);
 667     }
 668 
 669     /**
 670      * Reads a signed eight-bit value from this file. This method reads a
 671      * byte from the file, starting from the current file pointer.
 672      * If the byte read is <code>b</code>, where
 673      * <code>0&nbsp;&lt;=&nbsp;b&nbsp;&lt;=&nbsp;255</code>,
 674      * then the result is:
 675      * <blockquote><pre>
 676      *     (byte)(b)
 677      * </pre></blockquote>
 678      * <p>
 679      * This method blocks until the byte is read, the end of the stream
 680      * is detected, or an exception is thrown.
 681      *
 682      * @return     the next byte of this file as a signed eight-bit
 683      *             <code>byte</code>.
 684      * @exception  EOFException  if this file has reached the end.
 685      * @exception  IOException   if an I/O error occurs.
 686      */
 687     public final byte readByte() throws IOException {
 688         int ch = this.read();
 689         if (ch < 0)
 690             throw new EOFException();
 691         return (byte)(ch);
 692     }
 693 
 694     /**
 695      * Reads an unsigned eight-bit number from this file. This method reads
 696      * a byte from this file, starting at the current file pointer,
 697      * and returns that byte.
 698      * <p>
 699      * This method blocks until the byte is read, the end of the stream
 700      * is detected, or an exception is thrown.
 701      *
 702      * @return     the next byte of this file, interpreted as an unsigned
 703      *             eight-bit number.
 704      * @exception  EOFException  if this file has reached the end.
 705      * @exception  IOException   if an I/O error occurs.
 706      */
 707     public final int readUnsignedByte() throws IOException {
 708         int ch = this.read();
 709         if (ch < 0)
 710             throw new EOFException();
 711         return ch;
 712     }
 713 
 714     /**
 715      * Reads a signed 16-bit number from this file. The method reads two
 716      * bytes from this file, starting at the current file pointer.
 717      * If the two bytes read, in order, are
 718      * <code>b1</code> and <code>b2</code>, where each of the two values is
 719      * between <code>0</code> and <code>255</code>, inclusive, then the
 720      * result is equal to:
 721      * <blockquote><pre>
 722      *     (short)((b1 &lt;&lt; 8) | b2)
 723      * </pre></blockquote>
 724      * <p>
 725      * This method blocks until the two bytes are read, the end of the
 726      * stream is detected, or an exception is thrown.
 727      *
 728      * @return     the next two bytes of this file, interpreted as a signed
 729      *             16-bit number.
 730      * @exception  EOFException  if this file reaches the end before reading
 731      *               two bytes.
 732      * @exception  IOException   if an I/O error occurs.
 733      */
 734     public final short readShort() throws IOException {
 735         int ch1 = this.read();
 736         int ch2 = this.read();
 737         if ((ch1 | ch2) < 0)
 738             throw new EOFException();
 739         return (short)((ch1 << 8) + (ch2 << 0));
 740     }
 741 
 742     /**
 743      * Reads an unsigned 16-bit number from this file. This method reads
 744      * two bytes from the file, starting at the current file pointer.
 745      * If the bytes read, in order, are
 746      * <code>b1</code> and <code>b2</code>, where
 747      * <code>0&nbsp;&lt;=&nbsp;b1, b2&nbsp;&lt;=&nbsp;255</code>,
 748      * then the result is equal to:
 749      * <blockquote><pre>
 750      *     (b1 &lt;&lt; 8) | b2
 751      * </pre></blockquote>
 752      * <p>
 753      * This method blocks until the two bytes are read, the end of the
 754      * stream is detected, or an exception is thrown.
 755      *
 756      * @return     the next two bytes of this file, interpreted as an unsigned
 757      *             16-bit integer.
 758      * @exception  EOFException  if this file reaches the end before reading
 759      *               two bytes.
 760      * @exception  IOException   if an I/O error occurs.
 761      */
 762     public final int readUnsignedShort() throws IOException {
 763         int ch1 = this.read();
 764         int ch2 = this.read();
 765         if ((ch1 | ch2) < 0)
 766             throw new EOFException();
 767         return (ch1 << 8) + (ch2 << 0);
 768     }
 769 
 770     /**
 771      * Reads a character from this file. This method reads two
 772      * bytes from the file, starting at the current file pointer.
 773      * If the bytes read, in order, are
 774      * <code>b1</code> and <code>b2</code>, where
 775      * <code>0&nbsp;&lt;=&nbsp;b1,&nbsp;b2&nbsp;&lt;=&nbsp;255</code>,
 776      * then the result is equal to:
 777      * <blockquote><pre>
 778      *     (char)((b1 &lt;&lt; 8) | b2)
 779      * </pre></blockquote>
 780      * <p>
 781      * This method blocks until the two bytes are read, the end of the
 782      * stream is detected, or an exception is thrown.
 783      *
 784      * @return     the next two bytes of this file, interpreted as a
 785      *                  <code>char</code>.
 786      * @exception  EOFException  if this file reaches the end before reading
 787      *               two bytes.
 788      * @exception  IOException   if an I/O error occurs.
 789      */
 790     public final char readChar() throws IOException {
 791         int ch1 = this.read();
 792         int ch2 = this.read();
 793         if ((ch1 | ch2) < 0)
 794             throw new EOFException();
 795         return (char)((ch1 << 8) + (ch2 << 0));
 796     }
 797 
 798     /**
 799      * Reads a signed 32-bit integer from this file. This method reads 4
 800      * bytes from the file, starting at the current file pointer.
 801      * If the bytes read, in order, are <code>b1</code>,
 802      * <code>b2</code>, <code>b3</code>, and <code>b4</code>, where
 803      * <code>0&nbsp;&lt;=&nbsp;b1, b2, b3, b4&nbsp;&lt;=&nbsp;255</code>,
 804      * then the result is equal to:
 805      * <blockquote><pre>
 806      *     (b1 &lt;&lt; 24) | (b2 &lt;&lt; 16) + (b3 &lt;&lt; 8) + b4
 807      * </pre></blockquote>
 808      * <p>
 809      * This method blocks until the four bytes are read, the end of the
 810      * stream is detected, or an exception is thrown.
 811      *
 812      * @return     the next four bytes of this file, interpreted as an
 813      *             <code>int</code>.
 814      * @exception  EOFException  if this file reaches the end before reading
 815      *               four bytes.
 816      * @exception  IOException   if an I/O error occurs.
 817      */
 818     public final int readInt() throws IOException {
 819         int ch1 = this.read();
 820         int ch2 = this.read();
 821         int ch3 = this.read();
 822         int ch4 = this.read();
 823         if ((ch1 | ch2 | ch3 | ch4) < 0)
 824             throw new EOFException();
 825         return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
 826     }
 827 
 828     /**
 829      * Reads a signed 64-bit integer from this file. This method reads eight
 830      * bytes from the file, starting at the current file pointer.
 831      * If the bytes read, in order, are
 832      * <code>b1</code>, <code>b2</code>, <code>b3</code>,
 833      * <code>b4</code>, <code>b5</code>, <code>b6</code>,
 834      * <code>b7</code>, and <code>b8,</code> where:
 835      * <blockquote><pre>
 836      *     0 &lt;= b1, b2, b3, b4, b5, b6, b7, b8 &lt;=255,
 837      * </pre></blockquote>
 838      * <p>
 839      * then the result is equal to:
 840      * <p><blockquote><pre>
 841      *     ((long)b1 &lt;&lt; 56) + ((long)b2 &lt;&lt; 48)
 842      *     + ((long)b3 &lt;&lt; 40) + ((long)b4 &lt;&lt; 32)
 843      *     + ((long)b5 &lt;&lt; 24) + ((long)b6 &lt;&lt; 16)
 844      *     + ((long)b7 &lt;&lt; 8) + b8
 845      * </pre></blockquote>
 846      * <p>
 847      * This method blocks until the eight bytes are read, the end of the
 848      * stream is detected, or an exception is thrown.
 849      *
 850      * @return     the next eight bytes of this file, interpreted as a
 851      *             <code>long</code>.
 852      * @exception  EOFException  if this file reaches the end before reading
 853      *               eight bytes.
 854      * @exception  IOException   if an I/O error occurs.
 855      */
 856     public final long readLong() throws IOException {
 857         return ((long)(readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
 858     }
 859 
 860     /**
 861      * Reads a <code>float</code> from this file. This method reads an
 862      * <code>int</code> value, starting at the current file pointer,
 863      * as if by the <code>readInt</code> method
 864      * and then converts that <code>int</code> to a <code>float</code>
 865      * using the <code>intBitsToFloat</code> method in class
 866      * <code>Float</code>.
 867      * <p>
 868      * This method blocks until the four bytes are read, the end of the
 869      * stream is detected, or an exception is thrown.
 870      *
 871      * @return     the next four bytes of this file, interpreted as a
 872      *             <code>float</code>.
 873      * @exception  EOFException  if this file reaches the end before reading
 874      *             four bytes.
 875      * @exception  IOException   if an I/O error occurs.
 876      * @see        java.io.RandomAccessFile#readInt()
 877      * @see        java.lang.Float#intBitsToFloat(int)
 878      */
 879     public final float readFloat() throws IOException {
 880         return Float.intBitsToFloat(readInt());
 881     }
 882 
 883     /**
 884      * Reads a <code>double</code> from this file. This method reads a
 885      * <code>long</code> value, starting at the current file pointer,
 886      * as if by the <code>readLong</code> method
 887      * and then converts that <code>long</code> to a <code>double</code>
 888      * using the <code>longBitsToDouble</code> method in
 889      * class <code>Double</code>.
 890      * <p>
 891      * This method blocks until the eight bytes are read, the end of the
 892      * stream is detected, or an exception is thrown.
 893      *
 894      * @return     the next eight bytes of this file, interpreted as a
 895      *             <code>double</code>.
 896      * @exception  EOFException  if this file reaches the end before reading
 897      *             eight bytes.
 898      * @exception  IOException   if an I/O error occurs.
 899      * @see        java.io.RandomAccessFile#readLong()
 900      * @see        java.lang.Double#longBitsToDouble(long)
 901      */
 902     public final double readDouble() throws IOException {
 903         return Double.longBitsToDouble(readLong());
 904     }
 905 
 906     /**
 907      * Reads the next line of text from this file.  This method successively
 908      * reads bytes from the file, starting at the current file pointer,
 909      * until it reaches a line terminator or the end
 910      * of the file.  Each byte is converted into a character by taking the
 911      * byte's value for the lower eight bits of the character and setting the
 912      * high eight bits of the character to zero.  This method does not,
 913      * therefore, support the full Unicode character set.
 914      *
 915      * <p> A line of text is terminated by a carriage-return character
 916      * (<code>'&#92;r'</code>), a newline character (<code>'&#92;n'</code>), a
 917      * carriage-return character immediately followed by a newline character,
 918      * or the end of the file.  Line-terminating characters are discarded and
 919      * are not included as part of the string returned.
 920      *
 921      * <p> This method blocks until a newline character is read, a carriage
 922      * return and the byte following it are read (to see if it is a newline),
 923      * the end of the file is reached, or an exception is thrown.
 924      *
 925      * @return     the next line of text from this file, or null if end
 926      *             of file is encountered before even one byte is read.
 927      * @exception  IOException  if an I/O error occurs.
 928      */
 929 
 930     public final String readLine() throws IOException {
 931         StringBuffer input = new StringBuffer();
 932         int c = -1;
 933         boolean eol = false;
 934 
 935         while (!eol) {
 936             switch (c = read()) {
 937             case -1:
 938             case '\n':
 939                 eol = true;
 940                 break;
 941             case '\r':
 942                 eol = true;
 943                 long cur = getFilePointer();
 944                 if ((read()) != '\n') {
 945                     seek(cur);
 946                 }
 947                 break;
 948             default:
 949                 input.append((char)c);
 950                 break;
 951             }
 952         }
 953 
 954         if ((c == -1) && (input.length() == 0)) {
 955             return null;
 956         }
 957         return input.toString();
 958     }
 959 
 960     /**
 961      * Reads in a string from this file. The string has been encoded
 962      * using a
 963      * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
 964      * format.
 965      * <p>
 966      * The first two bytes are read, starting from the current file
 967      * pointer, as if by
 968      * <code>readUnsignedShort</code>. This value gives the number of
 969      * following bytes that are in the encoded string, not
 970      * the length of the resulting string. The following bytes are then
 971      * interpreted as bytes encoding characters in the modified UTF-8 format
 972      * and are converted into characters.
 973      * <p>
 974      * This method blocks until all the bytes are read, the end of the
 975      * stream is detected, or an exception is thrown.
 976      *
 977      * @return     a Unicode string.
 978      * @exception  EOFException            if this file reaches the end before
 979      *               reading all the bytes.
 980      * @exception  IOException             if an I/O error occurs.
 981      * @exception  UTFDataFormatException  if the bytes do not represent
 982      *               valid modified UTF-8 encoding of a Unicode string.
 983      * @see        java.io.RandomAccessFile#readUnsignedShort()
 984      */
 985     public final String readUTF() throws IOException {
 986         return DataInputStream.readUTF(this);
 987     }
 988 
 989     /**
 990      * Writes a <code>boolean</code> to the file as a one-byte value. The
 991      * value <code>true</code> is written out as the value
 992      * <code>(byte)1</code>; the value <code>false</code> is written out
 993      * as the value <code>(byte)0</code>. The write starts at
 994      * the current position of the file pointer.
 995      *
 996      * @param      v   a <code>boolean</code> value to be written.
 997      * @exception  IOException  if an I/O error occurs.
 998      */
 999     public final void writeBoolean(boolean v) throws IOException {
1000         write(v ? 1 : 0);
1001         //written++;
1002     }
1003 
1004     /**
1005      * Writes a <code>byte</code> to the file as a one-byte value. The
1006      * write starts at the current position of the file pointer.
1007      *
1008      * @param      v   a <code>byte</code> value to be written.
1009      * @exception  IOException  if an I/O error occurs.
1010      */
1011     public final void writeByte(int v) throws IOException {
1012         write(v);
1013         //written++;
1014     }
1015 
1016     /**
1017      * Writes a <code>short</code> to the file as two bytes, high byte first.
1018      * The write starts at the current position of the file pointer.
1019      *
1020      * @param      v   a <code>short</code> to be written.
1021      * @exception  IOException  if an I/O error occurs.
1022      */
1023     public final void writeShort(int v) throws IOException {
1024         write((v >>> 8) & 0xFF);
1025         write((v >>> 0) & 0xFF);
1026         //written += 2;
1027     }
1028 
1029     /**
1030      * Writes a <code>char</code> to the file as a two-byte value, high
1031      * byte first. The write starts at the current position of the
1032      * file pointer.
1033      *
1034      * @param      v   a <code>char</code> value to be written.
1035      * @exception  IOException  if an I/O error occurs.
1036      */
1037     public final void writeChar(int v) throws IOException {
1038         write((v >>> 8) & 0xFF);
1039         write((v >>> 0) & 0xFF);
1040         //written += 2;
1041     }
1042 
1043     /**
1044      * Writes an <code>int</code> to the file as four bytes, high byte first.
1045      * The write starts at the current position of the file pointer.
1046      *
1047      * @param      v   an <code>int</code> to be written.
1048      * @exception  IOException  if an I/O error occurs.
1049      */
1050     public final void writeInt(int v) throws IOException {
1051         write((v >>> 24) & 0xFF);
1052         write((v >>> 16) & 0xFF);
1053         write((v >>>  8) & 0xFF);
1054         write((v >>>  0) & 0xFF);
1055         //written += 4;
1056     }
1057 
1058     /**
1059      * Writes a <code>long</code> to the file as eight bytes, high byte first.
1060      * The write starts at the current position of the file pointer.
1061      *
1062      * @param      v   a <code>long</code> to be written.
1063      * @exception  IOException  if an I/O error occurs.
1064      */
1065     public final void writeLong(long v) throws IOException {
1066         write((int)(v >>> 56) & 0xFF);
1067         write((int)(v >>> 48) & 0xFF);
1068         write((int)(v >>> 40) & 0xFF);
1069         write((int)(v >>> 32) & 0xFF);
1070         write((int)(v >>> 24) & 0xFF);
1071         write((int)(v >>> 16) & 0xFF);
1072         write((int)(v >>>  8) & 0xFF);
1073         write((int)(v >>>  0) & 0xFF);
1074         //written += 8;
1075     }
1076 
1077     /**
1078      * Converts the float argument to an <code>int</code> using the
1079      * <code>floatToIntBits</code> method in class <code>Float</code>,
1080      * and then writes that <code>int</code> value to the file as a
1081      * four-byte quantity, high byte first. The write starts at the
1082      * current position of the file pointer.
1083      *
1084      * @param      v   a <code>float</code> value to be written.
1085      * @exception  IOException  if an I/O error occurs.
1086      * @see        java.lang.Float#floatToIntBits(float)
1087      */
1088     public final void writeFloat(float v) throws IOException {
1089         writeInt(Float.floatToIntBits(v));
1090     }
1091 
1092     /**
1093      * Converts the double argument to a <code>long</code> using the
1094      * <code>doubleToLongBits</code> method in class <code>Double</code>,
1095      * and then writes that <code>long</code> value to the file as an
1096      * eight-byte quantity, high byte first. The write starts at the current
1097      * position of the file pointer.
1098      *
1099      * @param      v   a <code>double</code> value to be written.
1100      * @exception  IOException  if an I/O error occurs.
1101      * @see        java.lang.Double#doubleToLongBits(double)
1102      */
1103     public final void writeDouble(double v) throws IOException {
1104         writeLong(Double.doubleToLongBits(v));
1105     }
1106 
1107     /**
1108      * Writes the string to the file as a sequence of bytes. Each
1109      * character in the string is written out, in sequence, by discarding
1110      * its high eight bits. The write starts at the current position of
1111      * the file pointer.
1112      *
1113      * @param      s   a string of bytes to be written.
1114      * @exception  IOException  if an I/O error occurs.
1115      */
1116     public final void writeBytes(String s) throws IOException {
1117         int len = s.length();
1118         byte[] b = new byte[len];
1119         s.getBytes(0, len, b, 0);
1120         writeBytes(b, 0, len);
1121     }
1122 
1123     /**
1124      * Writes a string to the file as a sequence of characters. Each
1125      * character is written to the data output stream as if by the
1126      * <code>writeChar</code> method. The write starts at the current
1127      * position of the file pointer.
1128      *
1129      * @param      s   a <code>String</code> value to be written.
1130      * @exception  IOException  if an I/O error occurs.
1131      * @see        java.io.RandomAccessFile#writeChar(int)
1132      */
1133     public final void writeChars(String s) throws IOException {
1134         int clen = s.length();
1135         int blen = 2*clen;
1136         byte[] b = new byte[blen];
1137         char[] c = new char[clen];
1138         s.getChars(0, clen, c, 0);
1139         for (int i = 0, j = 0; i < clen; i++) {
1140             b[j++] = (byte)(c[i] >>> 8);
1141             b[j++] = (byte)(c[i] >>> 0);
1142         }
1143         writeBytes(b, 0, blen);
1144     }
1145 
1146     /**
1147      * Writes a string to the file using
1148      * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
1149      * encoding in a machine-independent manner.
1150      * <p>
1151      * First, two bytes are written to the file, starting at the
1152      * current file pointer, as if by the
1153      * <code>writeShort</code> method giving the number of bytes to
1154      * follow. This value is the number of bytes actually written out,
1155      * not the length of the string. Following the length, each character
1156      * of the string is output, in sequence, using the modified UTF-8 encoding
1157      * for each character.
1158      *
1159      * @param      str   a string to be written.
1160      * @exception  IOException  if an I/O error occurs.
1161      */
1162     public final void writeUTF(String str) throws IOException {
1163         DataOutputStream.writeUTF(str, this);
1164     }
1165 
1166     private static native void initIDs();
1167 
1168     private native void close0() throws IOException;
1169 
1170     static {
1171         initIDs();
1172     }
1173 }
--- EOF ---