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

Print this page
rev 6099 : [mq]: 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} method and set by the {@code seek}
  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} (which is a kind of
  50  * {@code IOException}) is thrown. If any byte cannot be read for
  51  * any reason other than end-of-file, an {@code IOException} other
  52  * than {@code EOFException} is thrown. In particular, an
  53  * {@code IOException} 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      *


 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.attach(this);

 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) {
 246             return fd;
 247         }
 248         throw new IOException();
 249     }
 250 
 251     /**
 252      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 253      * object associated with this file.
 254      *
 255      * <p> The {@link java.nio.channels.FileChannel#position()
 256      * position} of the returned channel will always be equal to
 257      * this object's file-pointer offset as returned by the {@link
 258      * #getFilePointer getFilePointer} method.  Changing this object's
 259      * file-pointer offset, whether explicitly or by reading or writing bytes,
 260      * will change the position of the channel, and vice versa.  Changing the
 261      * file's length via this object will change the length seen via the file
 262      * channel, and vice versa.
 263      *
 264      * @return  the file channel associated with this file
 265      *
 266      * @since 1.4
 267      * @spec JSR-51
 268      */
 269     public final FileChannel getChannel() {
 270         synchronized (this) {
 271             if (channel == null) {
 272                 channel = FileChannelImpl.open(fd, true, rw, this);
 273             }
 274             return channel;
 275         }
 276     }
 277 
 278     /**
 279      * Opens a file and returns the file descriptor.  The file is
 280      * opened in read-write mode if the O_RDWR bit in {@code mode}
 281      * is true, else the file is opened as read-only.
 282      * If the {@code name} refers to a directory, an IOException
 283      * is thrown.
 284      *
 285      * @param name the name of the file
 286      * @param mode the mode flags, a combination of the O_ constants
 287      *             defined above
 288      */
 289     private native void open(String name, int mode)
 290         throws FileNotFoundException;
 291 
 292     // 'Read' primitives
 293 
 294     /**
 295      * Reads a byte of data from this file. The byte is returned as an
 296      * integer in the range 0 to 255 ({@code 0x00-0x0ff}). This
 297      * method blocks if no input is yet available.
 298      * <p>
 299      * Although {@code RandomAccessFile} is not a subclass of
 300      * {@code InputStream}, this method behaves in exactly the same
 301      * way as the {@link InputStream#read()} method of
 302      * {@code InputStream}.
 303      *
 304      * @return     the next byte of data, or {@code -1} if the end of the
 305      *             file has been reached.
 306      * @exception  IOException  if an I/O error occurs. Not thrown if
 307      *                          end-of-file has been reached.
 308      */
 309     public native int read() throws IOException;











 310 
 311     /**
 312      * Reads a sub array as a sequence of bytes.
 313      * @param b the buffer into which the data is read.
 314      * @param off the start offset of the data.
 315      * @param len the number of bytes to read.
 316      * @exception IOException If an I/O error has occurred.
 317      */
 318     private native int readBytes(byte b[], int off, int len) throws IOException;











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


 437         len = length();
 438         newpos = pos + n;
 439         if (newpos > len) {
 440             newpos = len;
 441         }
 442         seek(newpos);
 443 
 444         /* return the actual number of bytes skipped */
 445         return (int) (newpos - pos);
 446     }
 447 
 448     // 'Write' primitives
 449 
 450     /**
 451      * Writes the specified byte to this file. The write starts at
 452      * the current file pointer.
 453      *
 454      * @param      b   the {@code byte} to be written.
 455      * @exception  IOException  if an I/O error occurs.
 456      */
 457     public native void write(int b) throws IOException;











 458 
 459     /**
 460      * Writes a sub array as a sequence of bytes.
 461      * @param b the data to be written
 462 
 463      * @param off the start offset in the data
 464      * @param len the number of bytes that are written
 465      * @exception IOException If an I/O error has occurred.
 466      */
 467     private native void writeBytes(byte b[], int off, int len) throws IOException;











 468 
 469     /**
 470      * Writes {@code b.length} bytes from the specified byte array
 471      * to this file, starting at the current file pointer.
 472      *
 473      * @param      b   the data.
 474      * @exception  IOException  if an I/O error occurs.
 475      */
 476     public void write(byte b[]) throws IOException {
 477         writeBytes(b, 0, b.length);
 478     }
 479 
 480     /**
 481      * Writes {@code len} bytes from the specified byte array
 482      * starting at offset {@code off} to this file.
 483      *
 484      * @param      b     the data.
 485      * @param      off   the start offset in the data.
 486      * @param      len   the number of bytes to write.
 487      * @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 import sun.misc.IoTraceContext;
  32 
  33 
  34 /**
  35  * Instances of this class support both reading and writing to a
  36  * random access file. A random access file behaves like a large
  37  * array of bytes stored in the file system. There is a kind of cursor,
  38  * or index into the implied array, called the <em>file pointer</em>;
  39  * input operations read bytes starting at the file pointer and advance
  40  * the file pointer past the bytes read. If the random access file is
  41  * created in read/write mode, then output operations are also available;
  42  * output operations write bytes starting at the file pointer and advance
  43  * the file pointer past the bytes written. Output operations that write
  44  * past the current end of the implied array cause the array to be
  45  * extended. The file pointer can be read by the
  46  * {@code getFilePointer} method and set by the {@code seek}
  47  * method.
  48  * <p>
  49  * It is generally true of all the reading routines in this class that
  50  * if end-of-file is reached before the desired number of bytes has been
  51  * read, an {@code EOFException} (which is a kind of
  52  * {@code IOException}) is thrown. If any byte cannot be read for
  53  * any reason other than end-of-file, an {@code IOException} other
  54  * than {@code EOFException} is thrown. In particular, an
  55  * {@code IOException} may be thrown if the stream has been closed.
  56  *
  57  * @author  unascribed
  58  * @since   JDK1.0
  59  */
  60 
  61 public class RandomAccessFile implements DataOutput, DataInput, Closeable {
  62 
  63     private FileDescriptor fd;
  64     private FileChannel channel = null;
  65     private boolean rw;
  66     private final String path;
  67 
  68     private Object closeLock = new Object();
  69     private volatile boolean closed = false;
  70 
  71     private static final int O_RDONLY = 1;
  72     private static final int O_RDWR =   2;
  73     private static final int O_SYNC =   4;
  74     private static final int O_DSYNC =  8;
  75 
  76     /**
  77      * Creates a random access file stream to read from, and optionally
  78      * to write to, a file with the specified name. A new
  79      * {@link FileDescriptor} object is created to represent the
  80      * connection to the file.
  81      *
  82      * <p> The <tt>mode</tt> argument specifies the access mode with which the
  83      * file is to be opened.  The permitted values and their meanings are as
  84      * specified for the <a
  85      * href="#mode"><tt>RandomAccessFile(File,String)</tt></a> constructor.
  86      *


 216                     imode = -1;
 217             }
 218         }
 219         if (imode < 0)
 220             throw new IllegalArgumentException("Illegal mode \"" + mode
 221                                                + "\" must be one of "
 222                                                + "\"r\", \"rw\", \"rws\","
 223                                                + " or \"rwd\"");
 224         SecurityManager security = System.getSecurityManager();
 225         if (security != null) {
 226             security.checkRead(name);
 227             if (rw) {
 228                 security.checkWrite(name);
 229             }
 230         }
 231         if (name == null) {
 232             throw new NullPointerException();
 233         }
 234         fd = new FileDescriptor();
 235         fd.attach(this);
 236         this.path = name;
 237         open(name, imode);
 238     }
 239 
 240     /**
 241      * Returns the opaque file descriptor object associated with this
 242      * stream. </p>
 243      *
 244      * @return     the file descriptor object associated with this stream.
 245      * @exception  IOException  if an I/O error occurs.
 246      * @see        java.io.FileDescriptor
 247      */
 248     public final FileDescriptor getFD() throws IOException {
 249         if (fd != null) {
 250             return fd;
 251         }
 252         throw new IOException();
 253     }
 254 
 255     /**
 256      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
 257      * object associated with this file.
 258      *
 259      * <p> The {@link java.nio.channels.FileChannel#position()
 260      * position} of the returned channel will always be equal to
 261      * this object's file-pointer offset as returned by the {@link
 262      * #getFilePointer getFilePointer} method.  Changing this object's
 263      * file-pointer offset, whether explicitly or by reading or writing bytes,
 264      * will change the position of the channel, and vice versa.  Changing the
 265      * file's length via this object will change the length seen via the file
 266      * channel, and vice versa.
 267      *
 268      * @return  the file channel associated with this file
 269      *
 270      * @since 1.4
 271      * @spec JSR-51
 272      */
 273     public final FileChannel getChannel() {
 274         synchronized (this) {
 275             if (channel == null) {
 276                 channel = FileChannelImpl.open(fd, path, true, rw, this);
 277             }
 278             return channel;
 279         }
 280     }
 281 
 282     /**
 283      * Opens a file and returns the file descriptor.  The file is
 284      * opened in read-write mode if the O_RDWR bit in {@code mode}
 285      * is true, else the file is opened as read-only.
 286      * If the {@code name} refers to a directory, an IOException
 287      * is thrown.
 288      *
 289      * @param name the name of the file
 290      * @param mode the mode flags, a combination of the O_ constants
 291      *             defined above
 292      */
 293     private native void open(String name, int mode)
 294         throws FileNotFoundException;
 295 
 296     // 'Read' primitives
 297 
 298     /**
 299      * Reads a byte of data from this file. The byte is returned as an
 300      * integer in the range 0 to 255 ({@code 0x00-0x0ff}). This
 301      * method blocks if no input is yet available.
 302      * <p>
 303      * Although {@code RandomAccessFile} is not a subclass of
 304      * {@code InputStream}, this method behaves in exactly the same
 305      * way as the {@link InputStream#read()} method of
 306      * {@code InputStream}.
 307      *
 308      * @return     the next byte of data, or {@code -1} if the end of the
 309      *             file has been reached.
 310      * @exception  IOException  if an I/O error occurs. Not thrown if
 311      *                          end-of-file has been reached.
 312      */
 313     public int read() throws IOException {
 314         IoTraceContext traceContext = IoTrace.fileReadBegin(path);
 315         int v = 0;
 316         try {
 317             v = read0();
 318         } finally {
 319             IoTrace.fileReadEnd(traceContext, v == -1 ? 0 : 1);
 320         }
 321         return v;
 322     }
 323 
 324     private native int read0() throws IOException;
 325 
 326     /**
 327      * Reads a sub array as a sequence of bytes.
 328      * @param b the buffer into which the data is read.
 329      * @param off the start offset of the data.
 330      * @param len the number of bytes to read.
 331      * @exception IOException If an I/O error has occurred.
 332      */
 333     private int readBytes(byte b[], int off, int len) throws IOException {
 334         IoTraceContext traceContext = IoTrace.fileReadBegin(path);
 335         int v = 0;
 336         try {
 337             v = readBytes0(b, off, len);
 338         } finally {
 339             IoTrace.fileReadEnd(traceContext, v);
 340         }
 341         return v;
 342     }
 343 
 344     private native int readBytes0(byte b[], int off, int len) throws IOException;
 345 
 346     /**
 347      * Reads up to {@code len} bytes of data from this file into an
 348      * array of bytes. This method blocks until at least one byte of input
 349      * is available.
 350      * <p>
 351      * Although {@code RandomAccessFile} is not a subclass of
 352      * {@code InputStream}, this method behaves in exactly the
 353      * same way as the {@link InputStream#read(byte[], int, int)} method of
 354      * {@code InputStream}.
 355      *
 356      * @param      b     the buffer into which the data is read.
 357      * @param      off   the start offset in array {@code b}
 358      *                   at which the data is written.
 359      * @param      len   the maximum number of bytes read.
 360      * @return     the total number of bytes read into the buffer, or
 361      *             {@code -1} if there is no more data because the end of
 362      *             the file has been reached.
 363      * @exception  IOException If the first byte cannot be read for any reason
 364      * other than end of file, or if the random access file has been closed, or if


 463         len = length();
 464         newpos = pos + n;
 465         if (newpos > len) {
 466             newpos = len;
 467         }
 468         seek(newpos);
 469 
 470         /* return the actual number of bytes skipped */
 471         return (int) (newpos - pos);
 472     }
 473 
 474     // 'Write' primitives
 475 
 476     /**
 477      * Writes the specified byte to this file. The write starts at
 478      * the current file pointer.
 479      *
 480      * @param      b   the {@code byte} to be written.
 481      * @exception  IOException  if an I/O error occurs.
 482      */
 483     public void write(int b) throws IOException {
 484         IoTraceContext traceContext = IoTrace.fileWriteBegin(path);
 485         int v = 0;
 486         try {
 487             write0(b);
 488             v = 1;
 489         } finally {
 490             IoTrace.fileWriteEnd(traceContext, v);
 491         }
 492     }
 493 
 494     private native void write0(int b) throws IOException;
 495 
 496     /**
 497      * Writes a sub array as a sequence of bytes.
 498      * @param b the data to be written

 499      * @param off the start offset in the data
 500      * @param len the number of bytes that are written
 501      * @exception IOException If an I/O error has occurred.
 502      */
 503     private void writeBytes(byte b[], int off, int len) throws IOException {
 504         IoTraceContext traceContext = IoTrace.fileWriteBegin(path);
 505         int v = 0;
 506         try {
 507             writeBytes0(b, off, len);
 508             v = len;
 509         } finally {
 510             IoTrace.fileWriteEnd(traceContext, v);
 511         }
 512     }
 513 
 514     private native void writeBytes0(byte b[], int off, int len) throws IOException;
 515 
 516     /**
 517      * Writes {@code b.length} bytes from the specified byte array
 518      * to this file, starting at the current file pointer.
 519      *
 520      * @param      b   the data.
 521      * @exception  IOException  if an I/O error occurs.
 522      */
 523     public void write(byte b[]) throws IOException {
 524         writeBytes(b, 0, b.length);
 525     }
 526 
 527     /**
 528      * Writes {@code len} bytes from the specified byte array
 529      * starting at offset {@code off} to this file.
 530      *
 531      * @param      b     the data.
 532      * @param      off   the start offset in the data.
 533      * @param      len   the number of bytes to write.
 534      * @exception  IOException  if an I/O error occurs.