src/share/classes/java/io/RandomAccessFile.java

Print this page
rev 5501 : imported patch io-trace


  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 
  31 
  32 /**
  33  * Instances of this class support both reading and writing to a
  34  * random access file. A random access file behaves like a large
  35  * array of bytes stored in the file system. There is a kind of cursor,
  36  * or index into the implied array, called the <em>file pointer</em>;
  37  * input operations read bytes starting at the file pointer and advance
  38  * the file pointer past the bytes read. If the random access file is
  39  * created in read/write mode, then output operations are also available;
  40  * output operations write bytes starting at the file pointer and advance
  41  * the file pointer past the bytes written. Output operations that write
  42  * past the current end of the implied array cause the array to be
  43  * extended. The file pointer can be read by the
  44  * <code>getFilePointer</code> method and set by the <code>seek</code>
  45  * method.
  46  * <p>
  47  * It is generally true of all the reading routines in this class that
  48  * if end-of-file is reached before the desired number of bytes has been
  49  * read, an <code>EOFException</code> (which is a kind of
  50  * <code>IOException</code>) is thrown. If any byte cannot be read for
  51  * any reason other than end-of-file, an <code>IOException</code> other
  52  * than <code>EOFException</code> is thrown. In particular, an
  53  * <code>IOException</code> may be thrown if the stream has been closed.
  54  *
  55  * @author  unascribed
  56  * @since   JDK1.0
  57  */
  58 
  59 public class RandomAccessFile implements DataOutput, DataInput, Closeable {
  60 
  61     private FileDescriptor fd;
  62     private FileChannel channel = null;
  63     private boolean rw;
  64 



  65     private Object closeLock = new Object();
  66     private volatile boolean closed = false;
  67 
  68     private static final int O_RDONLY = 1;
  69     private static final int O_RDWR =   2;
  70     private static final int O_SYNC =   4;
  71     private static final int O_DSYNC =  8;
  72 
  73     /**
  74      * Creates a random access file stream to read from, and optionally
  75      * to write to, a file with the specified name. A new
  76      * {@link FileDescriptor} object is created to represent the
  77      * connection to the file.
  78      *
  79      * <p> The <tt>mode</tt> argument specifies the access mode with which the
  80      * file is to be opened.  The permitted values and their meanings are as
  81      * specified for the <a
  82      * href="#mode"><tt>RandomAccessFile(File,String)</tt></a> constructor.
  83      *
  84      * <p>


 213                     imode = -1;
 214             }
 215         }
 216         if (imode < 0)
 217             throw new IllegalArgumentException("Illegal mode \"" + mode
 218                                                + "\" must be one of "
 219                                                + "\"r\", \"rw\", \"rws\","
 220                                                + " or \"rwd\"");
 221         SecurityManager security = System.getSecurityManager();
 222         if (security != null) {
 223             security.checkRead(name);
 224             if (rw) {
 225                 security.checkWrite(name);
 226             }
 227         }
 228         if (name == null) {
 229             throw new NullPointerException();
 230         }
 231         fd = new FileDescriptor();
 232         fd.incrementAndGetUseCount();

 233         open(name, imode);
 234     }
 235 
 236     /**
 237      * Returns the opaque file descriptor object associated with this
 238      * stream. </p>
 239      *
 240      * @return     the file descriptor object associated with this stream.
 241      * @exception  IOException  if an I/O error occurs.
 242      * @see        java.io.FileDescriptor
 243      */
 244     public final FileDescriptor getFD() throws IOException {
 245         if (fd != null) return fd;
 246         throw new IOException();
 247     }
 248 
 249     /**
 250      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 251      * object associated with this file.
 252      *
 253      * <p> The {@link java.nio.channels.FileChannel#position()
 254      * </code>position<code>} of the returned channel will always be equal to
 255      * this object's file-pointer offset as returned by the {@link
 256      * #getFilePointer getFilePointer} method.  Changing this object's
 257      * file-pointer offset, whether explicitly or by reading or writing bytes,
 258      * will change the position of the channel, and vice versa.  Changing the
 259      * file's length via this object will change the length seen via the file
 260      * channel, and vice versa.
 261      *
 262      * @return  the file channel associated with this file
 263      *
 264      * @since 1.4
 265      * @spec JSR-51
 266      */
 267     public final FileChannel getChannel() {
 268         synchronized (this) {
 269             if (channel == null) {
 270                 channel = FileChannelImpl.open(fd, true, rw, this);
 271 
 272                 /*
 273                  * FileDescriptor could be shared by FileInputStream or
 274                  * FileOutputStream.
 275                  * Ensure that FD is GC'ed only when all the streams/channels
 276                  * are done using it.
 277                  * Increment fd's use count. Invoking the channel's close()
 278                  * method will result in decrementing the use count set for
 279                  * the channel.
 280                  */
 281                 fd.incrementAndGetUseCount();
 282             }
 283             return channel;
 284         }
 285     }
 286 
 287     /**
 288      * Opens a file and returns the file descriptor.  The file is
 289      * opened in read-write mode if the O_RDWR bit in <code>mode</code>
 290      * is true, else the file is opened as read-only.


 298     private native void open(String name, int mode)
 299         throws FileNotFoundException;
 300 
 301     // 'Read' primitives
 302 
 303     /**
 304      * Reads a byte of data from this file. The byte is returned as an
 305      * integer in the range 0 to 255 (<code>0x00-0x0ff</code>). This
 306      * method blocks if no input is yet available.
 307      * <p>
 308      * Although <code>RandomAccessFile</code> is not a subclass of
 309      * <code>InputStream</code>, this method behaves in exactly the same
 310      * way as the {@link InputStream#read()} method of
 311      * <code>InputStream</code>.
 312      *
 313      * @return     the next byte of data, or <code>-1</code> if the end of the
 314      *             file has been reached.
 315      * @exception  IOException  if an I/O error occurs. Not thrown if
 316      *                          end-of-file has been reached.
 317      */
 318     public native int read() throws IOException;











 319 
 320     /**
 321      * Reads a sub array as a sequence of bytes.
 322      * @param b the buffer into which the data is read.
 323      * @param off the start offset of the data.
 324      * @param len the number of bytes to read.
 325      * @exception IOException If an I/O error has occurred.
 326      */
 327     private native int readBytes(byte b[], int off, int len) throws IOException;











 328 
 329     /**
 330      * Reads up to <code>len</code> bytes of data from this file into an
 331      * array of bytes. This method blocks until at least one byte of input
 332      * is available.
 333      * <p>
 334      * Although <code>RandomAccessFile</code> is not a subclass of
 335      * <code>InputStream</code>, this method behaves in exactly the
 336      * same way as the {@link InputStream#read(byte[], int, int)} method of
 337      * <code>InputStream</code>.
 338      *
 339      * @param      b     the buffer into which the data is read.
 340      * @param      off   the start offset in array <code>b</code>
 341      *                   at which the data is written.
 342      * @param      len   the maximum number of bytes read.
 343      * @return     the total number of bytes read into the buffer, or
 344      *             <code>-1</code> if there is no more data because the end of
 345      *             the file has been reached.
 346      * @exception  IOException If the first byte cannot be read for any reason
 347      * other than end of file, or if the random access file has been closed, or if


 446         len = length();
 447         newpos = pos + n;
 448         if (newpos > len) {
 449             newpos = len;
 450         }
 451         seek(newpos);
 452 
 453         /* return the actual number of bytes skipped */
 454         return (int) (newpos - pos);
 455     }
 456 
 457     // 'Write' primitives
 458 
 459     /**
 460      * Writes the specified byte to this file. The write starts at
 461      * the current file pointer.
 462      *
 463      * @param      b   the <code>byte</code> to be written.
 464      * @exception  IOException  if an I/O error occurs.
 465      */
 466     public native void write(int b) throws IOException;











 467 
 468     /**
 469      * Writes a sub array as a sequence of bytes.
 470      * @param b the data to be written
 471 
 472      * @param off the start offset in the data
 473      * @param len the number of bytes that are written
 474      * @exception IOException If an I/O error has occurred.
 475      */
 476     private native void writeBytes(byte b[], int off, int len) throws IOException;











 477 
 478     /**
 479      * Writes <code>b.length</code> bytes from the specified byte array
 480      * to this file, starting at the current file pointer.
 481      *
 482      * @param      b   the data.
 483      * @exception  IOException  if an I/O error occurs.
 484      */
 485     public void write(byte b[]) throws IOException {
 486         writeBytes(b, 0, b.length);
 487     }
 488 
 489     /**
 490      * Writes <code>len</code> bytes from the specified byte array
 491      * starting at offset <code>off</code> to this file.
 492      *
 493      * @param      b     the data.
 494      * @param      off   the start offset in the data.
 495      * @param      len   the number of bytes to write.
 496      * @exception  IOException  if an I/O error occurs.




  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>


 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.


 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


 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.