Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2014 The Android Open Source Project
      3  * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
      4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      5  *
      6  * This code is free software; you can redistribute it and/or modify it
      7  * under the terms of the GNU General Public License version 2 only, as
      8  * published by the Free Software Foundation.  Oracle designates this
      9  * particular file as subject to the "Classpath" exception as provided
     10  * by Oracle in the LICENSE file that accompanied this code.
     11  *
     12  * This code is distributed in the hope that it will be useful, but WITHOUT
     13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  * version 2 for more details (a copy is included in the LICENSE file that
     16  * accompanied this code).
     17  *
     18  * You should have received a copy of the GNU General Public License version
     19  * 2 along with this work; if not, write to the Free Software Foundation,
     20  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     21  *
     22  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     23  * or visit www.oracle.com if you need additional information or have any
     24  * questions.
     25  */
     26 
     27 package java.io;
     28 
     29 import java.nio.channels.FileChannel;
     30 import sun.nio.ch.FileChannelImpl;
     31 import android.system.ErrnoException;
     32 import dalvik.system.CloseGuard;
     33 import libcore.io.IoBridge;
     34 import libcore.io.IoTracker;
     35 import libcore.io.Libcore;
     36 import static android.system.OsConstants.*;
     37 
     38 
     39 /**
     40  * Instances of this class support both reading and writing to a
     41  * random access file. A random access file behaves like a large
     42  * array of bytes stored in the file system. There is a kind of cursor,
     43  * or index into the implied array, called the <em>file pointer</em>;
     44  * input operations read bytes starting at the file pointer and advance
     45  * the file pointer past the bytes read. If the random access file is
     46  * created in read/write mode, then output operations are also available;
     47  * output operations write bytes starting at the file pointer and advance
     48  * the file pointer past the bytes written. Output operations that write
     49  * past the current end of the implied array cause the array to be
     50  * extended. The file pointer can be read by the
     51  * {@code getFilePointer} method and set by the {@code seek}
     52  * method.
     53  * <p>
     54  * It is generally true of all the reading routines in this class that
     55  * if end-of-file is reached before the desired number of bytes has been
     56  * read, an {@code EOFException} (which is a kind of
     57  * {@code IOException}) is thrown. If any byte cannot be read for
     58  * any reason other than end-of-file, an {@code IOException} other
     59  * than {@code EOFException} is thrown. In particular, an
     60  * {@code IOException} may be thrown if the stream has been closed.
     61  *
     62  * @author  unascribed
     63  * @since   JDK1.0
     64  */
     65 
     66 public class RandomAccessFile implements DataOutput, DataInput, Closeable {
     67 
     68     private final CloseGuard guard = CloseGuard.get();
     69     private final byte[] scratch = new byte[8];
     70     private boolean syncMetadata = false;
     71     private int mode;
     72 
     73     private FileDescriptor fd;
     74     private FileChannel channel = null;
     75     private boolean rw;
     76 
     77     /**
     78      * The path of the referenced file
     79      * (null if the stream is created with a file descriptor)
     80      */
     81     private final String path;
     82 
     83     private Object closeLock = new Object();
     84     private volatile boolean closed = false;
     85     /**
     86      * A single tracker to track both read and write. The tracker resets when the operation
     87      * performed is different from the operation last performed.
     88      */
     89     private final IoTracker ioTracker = new IoTracker();
     90 
     91     /**
     92      * Creates a random access file stream to read from, and optionally
     93      * to write to, a file with the specified name. A new
     94      * {@link FileDescriptor} object is created to represent the
     95      * connection to the file.
     96      *
     97      * <p> The <tt>mode</tt> argument specifies the access mode with which the
     98      * file is to be opened.  The permitted values and their meanings are as
     99      * specified for the <a
    100      * href="#mode"><tt>RandomAccessFile(File,String)</tt></a> constructor.
    101      *
    102      * <p>
    103      * If there is a security manager, its {@code checkRead} method
    104      * is called with the {@code name} argument
    105      * as its argument to see if read access to the file is allowed.
    106      * If the mode allows writing, the security manager's
    107      * {@code checkWrite} method
    108      * is also called with the {@code name} argument
    109      * as its argument to see if write access to the file is allowed.
    110      *
    111      * @param      name   the system-dependent filename
    112      * @param      mode   the access <a href="#mode">mode</a>
    113      * @exception  IllegalArgumentException  if the mode argument is not equal
    114      *               to one of <tt>"r"</tt>, <tt>"rw"</tt>, <tt>"rws"</tt>, or
    115      *               <tt>"rwd"</tt>
    116      * @exception FileNotFoundException
    117      *            if the mode is <tt>"r"</tt> but the given string does not
    118      *            denote an existing regular file, or if the mode begins with
    119      *            <tt>"rw"</tt> but the given string does not denote an
    120      *            existing, writable regular file and a new regular file of
    121      *            that name cannot be created, or if some other error occurs
    122      *            while opening or creating the file
    123      * @exception  SecurityException         if a security manager exists and its
    124      *               {@code checkRead} method denies read access to the file
    125      *               or the mode is "rw" and the security manager's
    126      *               {@code checkWrite} method denies write access to the file
    127      * @see        java.lang.SecurityException
    128      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
    129      * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
    130      * @revised 1.4
    131      * @spec JSR-51
    132      */
    133     public RandomAccessFile(String name, String mode)
    134         throws FileNotFoundException
    135     {
    136         this(name != null ? new File(name) : null, mode);
    137     }
    138 
    139     /**
    140      * Creates a random access file stream to read from, and optionally to
    141      * write to, the file specified by the {@link File} argument.  A new {@link
    142      * FileDescriptor} object is created to represent this file connection.
    143      *
    144      * <p>The <a name="mode"><tt>mode</tt></a> argument specifies the access mode
    145      * in which the file is to be opened.  The permitted values and their
    146      * meanings are:
    147      *
    148      * <table summary="Access mode permitted values and meanings">
    149      * <tr><th align="left">Value</th><th align="left">Meaning</th></tr>
    150      * <tr><td valign="top"><tt>"r"</tt></td>
    151      *     <td> Open for reading only.  Invoking any of the <tt>write</tt>
    152      *     methods of the resulting object will cause an {@link
    153      *     java.io.IOException} to be thrown. </td></tr>
    154      * <tr><td valign="top"><tt>"rw"</tt></td>
    155      *     <td> Open for reading and writing.  If the file does not already
    156      *     exist then an attempt will be made to create it. </td></tr>
    157      * <tr><td valign="top"><tt>"rws"</tt></td>
    158      *     <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
    159      *     require that every update to the file's content or metadata be
    160      *     written synchronously to the underlying storage device.  </td></tr>
    161      * <tr><td valign="top"><tt>"rwd"&nbsp;&nbsp;</tt></td>
    162      *     <td> Open for reading and writing, as with <tt>"rw"</tt>, and also
    163      *     require that every update to the file's content be written
    164      *     synchronously to the underlying storage device. </td></tr>
    165      * </table>
    166      *
    167      * The <tt>"rws"</tt> and <tt>"rwd"</tt> modes work much like the {@link
    168      * java.nio.channels.FileChannel#force(boolean) force(boolean)} method of
    169      * the {@link java.nio.channels.FileChannel} class, passing arguments of
    170      * <tt>true</tt> and <tt>false</tt>, respectively, except that they always
    171      * apply to every I/O operation and are therefore often more efficient.  If
    172      * the file resides on a local storage device then when an invocation of a
    173      * method of this class returns it is guaranteed that all changes made to
    174      * the file by that invocation will have been written to that device.  This
    175      * is useful for ensuring that critical information is not lost in the
    176      * event of a system crash.  If the file does not reside on a local device
    177      * then no such guarantee is made.
    178      *
    179      * <p>The <tt>"rwd"</tt> mode can be used to reduce the number of I/O
    180      * operations performed.  Using <tt>"rwd"</tt> only requires updates to the
    181      * file's content to be written to storage; using <tt>"rws"</tt> requires
    182      * updates to both the file's content and its metadata to be written, which
    183      * generally requires at least one more low-level I/O operation.
    184      *
    185      * <p>If there is a security manager, its {@code checkRead} method is
    186      * called with the pathname of the {@code file} argument as its
    187      * argument to see if read access to the file is allowed.  If the mode
    188      * allows writing, the security manager's {@code checkWrite} method is
    189      * also called with the path argument to see if write access to the file is
    190      * allowed.
    191      *
    192      * @param      file   the file object
    193      * @param      mode   the access mode, as described
    194      *                    <a href="#mode">above</a>
    195      * @exception  IllegalArgumentException  if the mode argument is not equal
    196      *               to one of <tt>"r"</tt>, <tt>"rw"</tt>, <tt>"rws"</tt>, or
    197      *               <tt>"rwd"</tt>
    198      * @exception FileNotFoundException
    199      *            if the mode is <tt>"r"</tt> but the given file object does
    200      *            not denote an existing regular file, or if the mode begins
    201      *            with <tt>"rw"</tt> but the given file object does not denote
    202      *            an existing, writable regular file and a new regular file of
    203      *            that name cannot be created, or if some other error occurs
    204      *            while opening or creating the file
    205      * @exception  SecurityException         if a security manager exists and its
    206      *               {@code checkRead} method denies read access to the file
    207      *               or the mode is "rw" and the security manager's
    208      *               {@code checkWrite} method denies write access to the file
    209      * @see        java.lang.SecurityManager#checkRead(java.lang.String)
    210      * @see        java.lang.SecurityManager#checkWrite(java.lang.String)
    211      * @see        java.nio.channels.FileChannel#force(boolean)
    212      * @revised 1.4
    213      * @spec JSR-51
    214      */
    215     public RandomAccessFile(File file, String mode)
    216         throws FileNotFoundException
    217     {
    218         String name = (file != null ? file.getPath() : null);
    219         this.mode = -1;
    220         if (mode.equals("r")) {
    221             this.mode = O_RDONLY;
    222         } else if (mode.startsWith("rw")) {
    223             // Android-changed: Added. O_CREAT
    224             this.mode = O_RDWR | O_CREAT;
    225             rw = true;
    226             if (mode.length() > 2) {
    227                 if (mode.equals("rws")) {
    228                     syncMetadata = true;
    229                 } else if (mode.equals("rwd")) {
    230                     // Android-changed: Should this be O_DSYNC and the above O_SYNC ?
    231                     this.mode |= O_SYNC;
    232                 } else {
    233                     this.mode = -1;
    234                 }
    235             }
    236         }
    237 
    238         if (this.mode < 0) {
    239             throw new IllegalArgumentException("Illegal mode \"" + mode
    240                                                + "\" must be one of "
    241                                                + "\"r\", \"rw\", \"rws\","
    242                                                + " or \"rwd\"");
    243         }
    244 
    245         if (name == null) {
    246             throw new NullPointerException("file == null");
    247         }
    248 
    249         if (file.isInvalid()) {
    250             throw new FileNotFoundException("Invalid file path");
    251         }
    252         this.path = name;
    253 
    254         // Android-changed: Use IoBridge.open() instead of open.
    255         fd = IoBridge.open(file.getPath(), this.mode);
    256         if (syncMetadata) {
    257             try {
    258                 fd.sync();
    259             } catch (IOException e) {
    260                 // Ignored
    261             }
    262         }
    263         guard.open("close");
    264     }
    265 
    266     /**
    267      * Returns the opaque file descriptor object associated with this
    268      * stream.
    269      *
    270      * @return     the file descriptor object associated with this stream.
    271      * @exception  IOException  if an I/O error occurs.
    272      * @see        java.io.FileDescriptor
    273      */
    274     public final FileDescriptor getFD() throws IOException {
    275         if (fd != null) {
    276             return fd;
    277         }
    278         throw new IOException();
    279     }
    280 
    281     /**
    282      * Returns the unique {@link java.nio.channels.FileChannel FileChannel}
    283      * object associated with this file.
    284      *
    285      * <p> The {@link java.nio.channels.FileChannel#position()
    286      * position} of the returned channel will always be equal to
    287      * this object's file-pointer offset as returned by the {@link
    288      * #getFilePointer getFilePointer} method.  Changing this object's
    289      * file-pointer offset, whether explicitly or by reading or writing bytes,
    290      * will change the position of the channel, and vice versa.  Changing the
    291      * file's length via this object will change the length seen via the file
    292      * channel, and vice versa.
    293      *
    294      * @return  the file channel associated with this file
    295      *
    296      * @since 1.4
    297      * @spec JSR-51
    298      */
    299     public final FileChannel getChannel() {
    300         synchronized (this) {
    301             if (channel == null) {
    302                 channel = FileChannelImpl.open(fd, path, true, rw, this);
    303             }
    304             return channel;
    305         }
    306     }
    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}). This
    311      * method blocks if no input is yet available.
    312      * <p>
    313      * Although {@code RandomAccessFile} is not a subclass of
    314      * {@code InputStream}, this method behaves in exactly the same
    315      * way as the {@link InputStream#read()} method of
    316      * {@code InputStream}.
    317      *
    318      * @return     the next byte of data, or {@code -1} 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         return (read(scratch, 0, 1) != -1) ? scratch[0] & 0xff : -1;
    325     }
    326 
    327     /**
    328      * Reads a sub array as a sequence of bytes.
    329      * @param b the buffer into which the data is read.
    330      * @param off the start offset of the data.
    331      * @param len the number of bytes to read.
    332      * @exception IOException If an I/O error has occurred.
    333      */
    334     private int readBytes(byte b[], int off, int len) throws IOException {
    335         ioTracker.trackIo(len, IoTracker.Mode.READ);
    336         return IoBridge.read(fd, b, off, len);
    337     }
    338 
    339     /**
    340      * Reads up to {@code len} bytes of data from this file into an
    341      * array of bytes. This method blocks until at least one byte of input
    342      * is available.
    343      * <p>
    344      * Although {@code RandomAccessFile} is not a subclass of
    345      * {@code InputStream}, this method behaves in exactly the
    346      * same way as the {@link InputStream#read(byte[], int, int)} method of
    347      * {@code InputStream}.
    348      *
    349      * @param      b     the buffer into which the data is read.
    350      * @param      off   the start offset in array {@code b}
    351      *                   at which the data is written.
    352      * @param      len   the maximum number of bytes read.
    353      * @return     the total number of bytes read into the buffer, or
    354      *             {@code -1} if there is no more data because the end of
    355      *             the file has been reached.
    356      * @exception  IOException If the first byte cannot be read for any reason
    357      * other than end of file, or if the random access file has been closed, or if
    358      * some other I/O error occurs.
    359      * @exception  NullPointerException If {@code b} is {@code null}.
    360      * @exception  IndexOutOfBoundsException If {@code off} is negative,
    361      * {@code len} is negative, or {@code len} is greater than
    362      * {@code b.length - off}
    363      */
    364     public int read(byte b[], int off, int len) throws IOException {
    365         return readBytes(b, off, len);
    366     }
    367 
    368     /**
    369      * Reads up to {@code b.length} bytes of data from this file
    370      * into an array of bytes. This method blocks until at least one byte
    371      * of input is available.
    372      * <p>
    373      * Although {@code RandomAccessFile} is not a subclass of
    374      * {@code InputStream}, this method behaves in exactly the
    375      * same way as the {@link InputStream#read(byte[])} method of
    376      * {@code InputStream}.
    377      *
    378      * @param      b   the buffer into which the data is read.
    379      * @return     the total number of bytes read into the buffer, or
    380      *             {@code -1} if there is no more data because the end of
    381      *             this file has been reached.
    382      * @exception  IOException If the first byte cannot be read for any reason
    383      * other than end of file, or if the random access file has been closed, or if
    384      * some other I/O error occurs.
    385      * @exception  NullPointerException If {@code b} is {@code null}.
    386      */
    387     public int read(byte b[]) throws IOException {
    388         return readBytes(b, 0, b.length);
    389     }
    390 
    391     /**
    392      * Reads {@code b.length} bytes from this file into the byte
    393      * array, starting at the current file pointer. This method reads
    394      * repeatedly from the file until the requested number of bytes are
    395      * read. This method blocks until the requested number of bytes are
    396      * read, the end of the stream is detected, or an exception is thrown.
    397      *
    398      * @param      b   the buffer into which the data is read.
    399      * @exception  EOFException  if this file reaches the end before reading
    400      *               all the bytes.
    401      * @exception  IOException   if an I/O error occurs.
    402      */
    403     public final void readFully(byte b[]) throws IOException {
    404         readFully(b, 0, b.length);
    405     }
    406 
    407     /**
    408      * Reads exactly {@code len} bytes from this file into the byte
    409      * array, starting at the current file pointer. This method reads
    410      * repeatedly from the file until the requested number of bytes are
    411      * read. This method blocks until the requested number of bytes are
    412      * read, the end of the stream is detected, or an exception is thrown.
    413      *
    414      * @param      b     the buffer into which the data is read.
    415      * @param      off   the start offset of the data.
    416      * @param      len   the number of bytes to read.
    417      * @exception  EOFException  if this file reaches the end before reading
    418      *               all the bytes.
    419      * @exception  IOException   if an I/O error occurs.
    420      */
    421     public final void readFully(byte b[], int off, int len) throws IOException {
    422         int n = 0;
    423         do {
    424             int count = this.read(b, off + n, len - n);
    425             if (count < 0)
    426                 throw new EOFException();
    427             n += count;
    428         } while (n < len);
    429     }
    430 
    431     /**
    432      * Attempts to skip over {@code n} bytes of input discarding the
    433      * skipped bytes.
    434      * <p>
    435      *
    436      * This method may skip over some smaller number of bytes, possibly zero.
    437      * This may result from any of a number of conditions; reaching end of
    438      * file before {@code n} bytes have been skipped is only one
    439      * possibility. This method never throws an {@code EOFException}.
    440      * The actual number of bytes skipped is returned.  If {@code n}
    441      * is negative, no bytes are skipped.
    442      *
    443      * @param      n   the number of bytes to be skipped.
    444      * @return     the actual number of bytes skipped.
    445      * @exception  IOException  if an I/O error occurs.
    446      */
    447     public int skipBytes(int n) throws IOException {
    448         long pos;
    449         long len;
    450         long newpos;
    451 
    452         if (n <= 0) {
    453             return 0;
    454         }
    455         pos = getFilePointer();
    456         len = length();
    457         newpos = pos + n;
    458         if (newpos > len) {
    459             newpos = len;
    460         }
    461         seek(newpos);
    462 
    463         /* return the actual number of bytes skipped */
    464         return (int) (newpos - pos);
    465     }
    466 
    467     // 'Write' primitives
    468 
    469     /**
    470      * Writes the specified byte to this file. The write starts at
    471      * the current file pointer.
    472      *
    473      * @param      b   the {@code byte} to be written.
    474      * @exception  IOException  if an I/O error occurs.
    475      */
    476     public void write(int b) throws IOException {
    477         scratch[0] = (byte) (b & 0xff);
    478         write(scratch, 0, 1);
    479     }
    480 
    481     /**
    482      * Writes a sub array as a sequence of bytes.
    483      * @param b the data to be written
    484      * @param off the start offset in the data
    485      * @param len the number of bytes that are written
    486      * @exception IOException If an I/O error has occurred.
    487      */
    488     private void writeBytes(byte b[], int off, int len) throws IOException {
    489         ioTracker.trackIo(len, IoTracker.Mode.WRITE);
    490         IoBridge.write(fd, b, off, len);
    491         // if we are in "rws" mode, attempt to sync file+metadata
    492         if (syncMetadata) {
    493             fd.sync();
    494         }
    495     }
    496 
    497     /**
    498      * Writes {@code b.length} bytes from the specified byte array
    499      * to this file, starting at the current file pointer.
    500      *
    501      * @param      b   the data.
    502      * @exception  IOException  if an I/O error occurs.
    503      */
    504     public void write(byte b[]) throws IOException {
    505         writeBytes(b, 0, b.length);
    506     }
    507 
    508     /**
    509      * Writes {@code len} bytes from the specified byte array
    510      * starting at offset {@code off} to this file.
    511      *
    512      * @param      b     the data.
    513      * @param      off   the start offset in the data.
    514      * @param      len   the number of bytes to write.
    515      * @exception  IOException  if an I/O error occurs.
    516      */
    517     public void write(byte b[], int off, int len) throws IOException {
    518         writeBytes(b, off, len);
    519     }
    520 
    521     // 'Random access' stuff
    522 
    523     /**
    524      * Returns the current offset in this file.
    525      *
    526      * @return     the offset from the beginning of the file, in bytes,
    527      *             at which the next read or write occurs.
    528      * @exception  IOException  if an I/O error occurs.
    529      */
    530     public long getFilePointer() throws IOException {
    531         try {
    532             return Libcore.os.lseek(fd, 0L, SEEK_CUR);
    533         } catch (ErrnoException errnoException) {
    534             throw errnoException.rethrowAsIOException();
    535         }
    536     }
    537 
    538     /**
    539      * Sets the file-pointer offset, measured from the beginning of this
    540      * file, at which the next read or write occurs.  The offset may be
    541      * set beyond the end of the file. Setting the offset beyond the end
    542      * of the file does not change the file length.  The file length will
    543      * change only by writing after the offset has been set beyond the end
    544      * of the file.
    545      *
    546      * @param      offset   the offset position, measured in bytes from the
    547      *                   beginning of the file, at which to set the file
    548      *                   pointer.
    549      * @exception  IOException  if {@code pos} is less than
    550      *                          {@code 0} or if an I/O error occurs.
    551      */
    552     public void seek(long offset) throws IOException {
    553         if (offset < 0) {
    554             throw new IOException("offset < 0: " + offset);
    555         }
    556         try {
    557             Libcore.os.lseek(fd, offset, SEEK_SET);
    558             ioTracker.reset();
    559         } catch (ErrnoException errnoException) {
    560             throw errnoException.rethrowAsIOException();
    561         }
    562     }
    563 
    564     /**
    565      * Returns the length of this file.
    566      *
    567      * @return     the length of this file, measured in bytes.
    568      * @exception  IOException  if an I/O error occurs.
    569      */
    570     public long length() throws IOException {
    571         try {
    572             return Libcore.os.fstat(fd).st_size;
    573         } catch (ErrnoException errnoException) {
    574             throw errnoException.rethrowAsIOException();
    575         }
    576     }
    577 
    578     /**
    579      * Sets the length of this file.
    580      *
    581      * <p> If the present length of the file as returned by the
    582      * {@code length} method is greater than the {@code newLength}
    583      * argument then the file will be truncated.  In this case, if the file
    584      * offset as returned by the {@code getFilePointer} method is greater
    585      * than {@code newLength} then after this method returns the offset
    586      * will be equal to {@code newLength}.
    587      *
    588      * <p> If the present length of the file as returned by the
    589      * {@code length} method is smaller than the {@code newLength}
    590      * argument then the file will be extended.  In this case, the contents of
    591      * the extended portion of the file are not defined.
    592      *
    593      * @param      newLength    The desired length of the file
    594      * @exception  IOException  If an I/O error occurs
    595      * @since      1.2
    596      */
    597     public void setLength(long newLength) throws IOException {
    598         if (newLength < 0) {
    599             throw new IllegalArgumentException("newLength < 0");
    600         }
    601         try {
    602             Libcore.os.ftruncate(fd, newLength);
    603         } catch (ErrnoException errnoException) {
    604             throw errnoException.rethrowAsIOException();
    605         }
    606 
    607         long filePointer = getFilePointer();
    608         if (filePointer > newLength) {
    609             seek(newLength);
    610         }
    611         // if we are in "rws" mode, attempt to sync file+metadata
    612         if (syncMetadata) {
    613             fd.sync();
    614         }
    615     }
    616 
    617 
    618     /**
    619      * Closes this random access file stream and releases any system
    620      * resources associated with the stream. A closed random access
    621      * file cannot perform input or output operations and cannot be
    622      * reopened.
    623      *
    624      * <p> If this file has an associated channel then the channel is closed
    625      * as well.
    626      *
    627      * @exception  IOException  if an I/O error occurs.
    628      *
    629      * @revised 1.4
    630      * @spec JSR-51
    631      */
    632     public void close() throws IOException {
    633         guard.close();
    634         synchronized (closeLock) {
    635             if (closed) {
    636                 return;
    637             }
    638             closed = true;
    639         }
    640 
    641         if (channel != null && channel.isOpen()) {
    642             channel.close();
    643         }
    644         IoBridge.closeAndSignalBlockedThreads(fd);
    645     }
    646 
    647     //
    648     //  Some "reading/writing Java data types" methods stolen from
    649     //  DataInputStream and DataOutputStream.
    650     //
    651 
    652     /**
    653      * Reads a {@code boolean} from this file. This method reads a
    654      * single byte from the file, starting at the current file pointer.
    655      * A value of {@code 0} represents
    656      * {@code false}. Any other value represents {@code true}.
    657      * This method blocks until the byte is read, the end of the stream
    658      * is detected, or an exception is thrown.
    659      *
    660      * @return     the {@code boolean} value read.
    661      * @exception  EOFException  if this file has reached the end.
    662      * @exception  IOException   if an I/O error occurs.
    663      */
    664     public final boolean readBoolean() throws IOException {
    665         int ch = this.read();
    666         if (ch < 0)
    667             throw new EOFException();
    668         return (ch != 0);
    669     }
    670 
    671     /**
    672      * Reads a signed eight-bit value from this file. This method reads a
    673      * byte from the file, starting from the current file pointer.
    674      * If the byte read is {@code b}, where
    675      * <code>0&nbsp;&lt;=&nbsp;b&nbsp;&lt;=&nbsp;255</code>,
    676      * then the result is:
    677      * <blockquote><pre>
    678      *     (byte)(b)
    679      * </pre></blockquote>
    680      * <p>
    681      * This method blocks until the byte is read, the end of the stream
    682      * is detected, or an exception is thrown.
    683      *
    684      * @return     the next byte of this file as a signed eight-bit
    685      *             {@code byte}.
    686      * @exception  EOFException  if this file has reached the end.
    687      * @exception  IOException   if an I/O error occurs.
    688      */
    689     public final byte readByte() throws IOException {
    690         int ch = this.read();
    691         if (ch < 0)
    692             throw new EOFException();
    693         return (byte)(ch);
    694     }
    695 
    696     /**
    697      * Reads an unsigned eight-bit number from this file. This method reads
    698      * a byte from this file, starting at the current file pointer,
    699      * and returns that byte.
    700      * <p>
    701      * This method blocks until the byte is read, the end of the stream
    702      * is detected, or an exception is thrown.
    703      *
    704      * @return     the next byte of this file, interpreted as an unsigned
    705      *             eight-bit number.
    706      * @exception  EOFException  if this file has reached the end.
    707      * @exception  IOException   if an I/O error occurs.
    708      */
    709     public final int readUnsignedByte() throws IOException {
    710         int ch = this.read();
    711         if (ch < 0)
    712             throw new EOFException();
    713         return ch;
    714     }
    715 
    716     /**
    717      * Reads a signed 16-bit number from this file. The method reads two
    718      * bytes from this file, starting at the current file pointer.
    719      * If the two bytes read, in order, are
    720      * {@code b1} and {@code b2}, where each of the two values is
    721      * between {@code 0} and {@code 255}, inclusive, then the
    722      * result is equal to:
    723      * <blockquote><pre>
    724      *     (short)((b1 &lt;&lt; 8) | b2)
    725      * </pre></blockquote>
    726      * <p>
    727      * This method blocks until the two bytes are read, the end of the
    728      * stream is detected, or an exception is thrown.
    729      *
    730      * @return     the next two bytes of this file, interpreted as a signed
    731      *             16-bit number.
    732      * @exception  EOFException  if this file reaches the end before reading
    733      *               two bytes.
    734      * @exception  IOException   if an I/O error occurs.
    735      */
    736     public final short readShort() throws IOException {
    737         int ch1 = this.read();
    738         int ch2 = this.read();
    739         if ((ch1 | ch2) < 0)
    740             throw new EOFException();
    741         return (short)((ch1 << 8) + (ch2 << 0));
    742     }
    743 
    744     /**
    745      * Reads an unsigned 16-bit number from this file. This method reads
    746      * two bytes from the file, starting at the current file pointer.
    747      * If the bytes read, in order, are
    748      * {@code b1} and {@code b2}, where
    749      * <code>0&nbsp;&lt;=&nbsp;b1, b2&nbsp;&lt;=&nbsp;255</code>,
    750      * then the result is equal to:
    751      * <blockquote><pre>
    752      *     (b1 &lt;&lt; 8) | b2
    753      * </pre></blockquote>
    754      * <p>
    755      * This method blocks until the two bytes are read, the end of the
    756      * stream is detected, or an exception is thrown.
    757      *
    758      * @return     the next two bytes of this file, interpreted as an unsigned
    759      *             16-bit integer.
    760      * @exception  EOFException  if this file reaches the end before reading
    761      *               two bytes.
    762      * @exception  IOException   if an I/O error occurs.
    763      */
    764     public final int readUnsignedShort() throws IOException {
    765         int ch1 = this.read();
    766         int ch2 = this.read();
    767         if ((ch1 | ch2) < 0)
    768             throw new EOFException();
    769         return (ch1 << 8) + (ch2 << 0);
    770     }
    771 
    772     /**
    773      * Reads a character from this file. This method reads two
    774      * bytes from the file, starting at the current file pointer.
    775      * If the bytes read, in order, are
    776      * {@code b1} and {@code b2}, where
    777      * <code>0&nbsp;&lt;=&nbsp;b1,&nbsp;b2&nbsp;&lt;=&nbsp;255</code>,
    778      * then the result is equal to:
    779      * <blockquote><pre>
    780      *     (char)((b1 &lt;&lt; 8) | b2)
    781      * </pre></blockquote>
    782      * <p>
    783      * This method blocks until the two bytes are read, the end of the
    784      * stream is detected, or an exception is thrown.
    785      *
    786      * @return     the next two bytes of this file, interpreted as a
    787      *                  {@code char}.
    788      * @exception  EOFException  if this file reaches the end before reading
    789      *               two bytes.
    790      * @exception  IOException   if an I/O error occurs.
    791      */
    792     public final char readChar() throws IOException {
    793         int ch1 = this.read();
    794         int ch2 = this.read();
    795         if ((ch1 | ch2) < 0)
    796             throw new EOFException();
    797         return (char)((ch1 << 8) + (ch2 << 0));
    798     }
    799 
    800     /**
    801      * Reads a signed 32-bit integer from this file. This method reads 4
    802      * bytes from the file, starting at the current file pointer.
    803      * If the bytes read, in order, are {@code b1},
    804      * {@code b2}, {@code b3}, and {@code b4}, where
    805      * <code>0&nbsp;&lt;=&nbsp;b1, b2, b3, b4&nbsp;&lt;=&nbsp;255</code>,
    806      * then the result is equal to:
    807      * <blockquote><pre>
    808      *     (b1 &lt;&lt; 24) | (b2 &lt;&lt; 16) + (b3 &lt;&lt; 8) + b4
    809      * </pre></blockquote>
    810      * <p>
    811      * This method blocks until the four bytes are read, the end of the
    812      * stream is detected, or an exception is thrown.
    813      *
    814      * @return     the next four bytes of this file, interpreted as an
    815      *             {@code int}.
    816      * @exception  EOFException  if this file reaches the end before reading
    817      *               four bytes.
    818      * @exception  IOException   if an I/O error occurs.
    819      */
    820     public final int readInt() throws IOException {
    821         int ch1 = this.read();
    822         int ch2 = this.read();
    823         int ch3 = this.read();
    824         int ch4 = this.read();
    825         if ((ch1 | ch2 | ch3 | ch4) < 0)
    826             throw new EOFException();
    827         return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
    828     }
    829 
    830     /**
    831      * Reads a signed 64-bit integer from this file. This method reads eight
    832      * bytes from the file, starting at the current file pointer.
    833      * If the bytes read, in order, are
    834      * {@code b1}, {@code b2}, {@code b3},
    835      * {@code b4}, {@code b5}, {@code b6},
    836      * {@code b7}, and {@code b8,} where:
    837      * <blockquote><pre>
    838      *     0 &lt;= b1, b2, b3, b4, b5, b6, b7, b8 &lt;=255,
    839      * </pre></blockquote>
    840      * <p>
    841      * then the result is equal to:
    842      * <blockquote><pre>
    843      *     ((long)b1 &lt;&lt; 56) + ((long)b2 &lt;&lt; 48)
    844      *     + ((long)b3 &lt;&lt; 40) + ((long)b4 &lt;&lt; 32)
    845      *     + ((long)b5 &lt;&lt; 24) + ((long)b6 &lt;&lt; 16)
    846      *     + ((long)b7 &lt;&lt; 8) + b8
    847      * </pre></blockquote>
    848      * <p>
    849      * This method blocks until the eight bytes are read, the end of the
    850      * stream is detected, or an exception is thrown.
    851      *
    852      * @return     the next eight bytes of this file, interpreted as a
    853      *             {@code long}.
    854      * @exception  EOFException  if this file reaches the end before reading
    855      *               eight bytes.
    856      * @exception  IOException   if an I/O error occurs.
    857      */
    858     public final long readLong() throws IOException {
    859         return ((long)(readInt()) << 32) + (readInt() & 0xFFFFFFFFL);
    860     }
    861 
    862     /**
    863      * Reads a {@code float} from this file. This method reads an
    864      * {@code int} value, starting at the current file pointer,
    865      * as if by the {@code readInt} method
    866      * and then converts that {@code int} to a {@code float}
    867      * using the {@code intBitsToFloat} method in class
    868      * {@code Float}.
    869      * <p>
    870      * This method blocks until the four bytes are read, the end of the
    871      * stream is detected, or an exception is thrown.
    872      *
    873      * @return     the next four bytes of this file, interpreted as a
    874      *             {@code float}.
    875      * @exception  EOFException  if this file reaches the end before reading
    876      *             four bytes.
    877      * @exception  IOException   if an I/O error occurs.
    878      * @see        java.io.RandomAccessFile#readInt()
    879      * @see        java.lang.Float#intBitsToFloat(int)
    880      */
    881     public final float readFloat() throws IOException {
    882         return Float.intBitsToFloat(readInt());
    883     }
    884 
    885     /**
    886      * Reads a {@code double} from this file. This method reads a
    887      * {@code long} value, starting at the current file pointer,
    888      * as if by the {@code readLong} method
    889      * and then converts that {@code long} to a {@code double}
    890      * using the {@code longBitsToDouble} method in
    891      * class {@code Double}.
    892      * <p>
    893      * This method blocks until the eight bytes are read, the end of the
    894      * stream is detected, or an exception is thrown.
    895      *
    896      * @return     the next eight bytes of this file, interpreted as a
    897      *             {@code double}.
    898      * @exception  EOFException  if this file reaches the end before reading
    899      *             eight bytes.
    900      * @exception  IOException   if an I/O error occurs.
    901      * @see        java.io.RandomAccessFile#readLong()
    902      * @see        java.lang.Double#longBitsToDouble(long)
    903      */
    904     public final double readDouble() throws IOException {
    905         return Double.longBitsToDouble(readLong());
    906     }
    907 
    908     /**
    909      * Reads the next line of text from this file.  This method successively
    910      * reads bytes from the file, starting at the current file pointer,
    911      * until it reaches a line terminator or the end
    912      * of the file.  Each byte is converted into a character by taking the
    913      * byte's value for the lower eight bits of the character and setting the
    914      * high eight bits of the character to zero.  This method does not,
    915      * therefore, support the full Unicode character set.
    916      *
    917      * <p> A line of text is terminated by a carriage-return character
    918      * ({@code '\u005Cr'}), a newline character ({@code '\u005Cn'}), a
    919      * carriage-return character immediately followed by a newline character,
    920      * or the end of the file.  Line-terminating characters are discarded and
    921      * are not included as part of the string returned.
    922      *
    923      * <p> This method blocks until a newline character is read, a carriage
    924      * return and the byte following it are read (to see if it is a newline),
    925      * the end of the file is reached, or an exception is thrown.
    926      *
    927      * @return     the next line of text from this file, or null if end
    928      *             of file is encountered before even one byte is read.
    929      * @exception  IOException  if an I/O error occurs.
    930      */
    931 
    932     public final String readLine() throws IOException {
    933         StringBuffer input = new StringBuffer();
    934         int c = -1;
    935         boolean eol = false;
    936 
    937         while (!eol) {
    938             switch (c = read()) {
    939             case -1:
    940             case '\n':
    941                 eol = true;
    942                 break;
    943             case '\r':
    944                 eol = true;
    945                 long cur = getFilePointer();
    946                 if ((read()) != '\n') {
    947                     seek(cur);
    948                 }
    949                 break;
    950             default:
    951                 input.append((char)c);
    952                 break;
    953             }
    954         }
    955 
    956         if ((c == -1) && (input.length() == 0)) {
    957             return null;
    958         }
    959         return input.toString();
    960     }
    961 
    962     /**
    963      * Reads in a string from this file. The string has been encoded
    964      * using a
    965      * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
    966      * format.
    967      * <p>
    968      * The first two bytes are read, starting from the current file
    969      * pointer, as if by
    970      * {@code readUnsignedShort}. This value gives the number of
    971      * following bytes that are in the encoded string, not
    972      * the length of the resulting string. The following bytes are then
    973      * interpreted as bytes encoding characters in the modified UTF-8 format
    974      * and are converted into characters.
    975      * <p>
    976      * This method blocks until all the bytes are read, the end of the
    977      * stream is detected, or an exception is thrown.
    978      *
    979      * @return     a Unicode string.
    980      * @exception  EOFException            if this file reaches the end before
    981      *               reading all the bytes.
    982      * @exception  IOException             if an I/O error occurs.
    983      * @exception  UTFDataFormatException  if the bytes do not represent
    984      *               valid modified UTF-8 encoding of a Unicode string.
    985      * @see        java.io.RandomAccessFile#readUnsignedShort()
    986      */
    987     public final String readUTF() throws IOException {
    988         return DataInputStream.readUTF(this);
    989     }
    990 
    991     /**
    992      * Writes a {@code boolean} to the file as a one-byte value. The
    993      * value {@code true} is written out as the value
    994      * {@code (byte)1}; the value {@code false} is written out
    995      * as the value {@code (byte)0}. The write starts at
    996      * the current position of the file pointer.
    997      *
    998      * @param      v   a {@code boolean} value to be written.
    999      * @exception  IOException  if an I/O error occurs.
   1000      */
   1001     public final void writeBoolean(boolean v) throws IOException {
   1002         write(v ? 1 : 0);
   1003         //written++;
   1004     }
   1005 
   1006     /**
   1007      * Writes a {@code byte} to the file as a one-byte value. The
   1008      * write starts at the current position of the file pointer.
   1009      *
   1010      * @param      v   a {@code byte} value to be written.
   1011      * @exception  IOException  if an I/O error occurs.
   1012      */
   1013     public final void writeByte(int v) throws IOException {
   1014         write(v);
   1015         //written++;
   1016     }
   1017 
   1018     /**
   1019      * Writes a {@code short} to the file as two bytes, high byte first.
   1020      * The write starts at the current position of the file pointer.
   1021      *
   1022      * @param      v   a {@code short} to be written.
   1023      * @exception  IOException  if an I/O error occurs.
   1024      */
   1025     public final void writeShort(int v) throws IOException {
   1026         write((v >>> 8) & 0xFF);
   1027         write((v >>> 0) & 0xFF);
   1028         //written += 2;
   1029     }
   1030 
   1031     /**
   1032      * Writes a {@code char} to the file as a two-byte value, high
   1033      * byte first. The write starts at the current position of the
   1034      * file pointer.
   1035      *
   1036      * @param      v   a {@code char} value to be written.
   1037      * @exception  IOException  if an I/O error occurs.
   1038      */
   1039     public final void writeChar(int v) throws IOException {
   1040         write((v >>> 8) & 0xFF);
   1041         write((v >>> 0) & 0xFF);
   1042         //written += 2;
   1043     }
   1044 
   1045     /**
   1046      * Writes an {@code int} to the file as four bytes, high byte first.
   1047      * The write starts at the current position of the file pointer.
   1048      *
   1049      * @param      v   an {@code int} to be written.
   1050      * @exception  IOException  if an I/O error occurs.
   1051      */
   1052     public final void writeInt(int v) throws IOException {
   1053         write((v >>> 24) & 0xFF);
   1054         write((v >>> 16) & 0xFF);
   1055         write((v >>>  8) & 0xFF);
   1056         write((v >>>  0) & 0xFF);
   1057         //written += 4;
   1058     }
   1059 
   1060     /**
   1061      * Writes a {@code long} to the file as eight bytes, high byte first.
   1062      * The write starts at the current position of the file pointer.
   1063      *
   1064      * @param      v   a {@code long} to be written.
   1065      * @exception  IOException  if an I/O error occurs.
   1066      */
   1067     public final void writeLong(long v) throws IOException {
   1068         write((int)(v >>> 56) & 0xFF);
   1069         write((int)(v >>> 48) & 0xFF);
   1070         write((int)(v >>> 40) & 0xFF);
   1071         write((int)(v >>> 32) & 0xFF);
   1072         write((int)(v >>> 24) & 0xFF);
   1073         write((int)(v >>> 16) & 0xFF);
   1074         write((int)(v >>>  8) & 0xFF);
   1075         write((int)(v >>>  0) & 0xFF);
   1076         //written += 8;
   1077     }
   1078 
   1079     /**
   1080      * Converts the float argument to an {@code int} using the
   1081      * {@code floatToIntBits} method in class {@code Float},
   1082      * and then writes that {@code int} value to the file as a
   1083      * four-byte quantity, high byte first. The write starts at the
   1084      * current position of the file pointer.
   1085      *
   1086      * @param      v   a {@code float} value to be written.
   1087      * @exception  IOException  if an I/O error occurs.
   1088      * @see        java.lang.Float#floatToIntBits(float)
   1089      */
   1090     public final void writeFloat(float v) throws IOException {
   1091         writeInt(Float.floatToIntBits(v));
   1092     }
   1093 
   1094     /**
   1095      * Converts the double argument to a {@code long} using the
   1096      * {@code doubleToLongBits} method in class {@code Double},
   1097      * and then writes that {@code long} value to the file as an
   1098      * eight-byte quantity, high byte first. The write starts at the current
   1099      * position of the file pointer.
   1100      *
   1101      * @param      v   a {@code double} value to be written.
   1102      * @exception  IOException  if an I/O error occurs.
   1103      * @see        java.lang.Double#doubleToLongBits(double)
   1104      */
   1105     public final void writeDouble(double v) throws IOException {
   1106         writeLong(Double.doubleToLongBits(v));
   1107     }
   1108 
   1109     /**
   1110      * Writes the string to the file as a sequence of bytes. Each
   1111      * character in the string is written out, in sequence, by discarding
   1112      * its high eight bits. The write starts at the current position of
   1113      * the file pointer.
   1114      *
   1115      * @param      s   a string of bytes to be written.
   1116      * @exception  IOException  if an I/O error occurs.
   1117      */
   1118     @SuppressWarnings("deprecation")
   1119     public final void writeBytes(String s) throws IOException {
   1120         int len = s.length();
   1121         byte[] b = new byte[len];
   1122         s.getBytes(0, len, b, 0);
   1123         writeBytes(b, 0, len);
   1124     }
   1125 
   1126     /**
   1127      * Writes a string to the file as a sequence of characters. Each
   1128      * character is written to the data output stream as if by the
   1129      * {@code writeChar} method. The write starts at the current
   1130      * position of the file pointer.
   1131      *
   1132      * @param      s   a {@code String} value to be written.
   1133      * @exception  IOException  if an I/O error occurs.
   1134      * @see        java.io.RandomAccessFile#writeChar(int)
   1135      */
   1136     public final void writeChars(String s) throws IOException {
   1137         int clen = s.length();
   1138         int blen = 2*clen;
   1139         byte[] b = new byte[blen];
   1140         char[] c = new char[clen];
   1141         s.getChars(0, clen, c, 0);
   1142         for (int i = 0, j = 0; i < clen; i++) {
   1143             b[j++] = (byte)(c[i] >>> 8);
   1144             b[j++] = (byte)(c[i] >>> 0);
   1145         }
   1146         writeBytes(b, 0, blen);
   1147     }
   1148 
   1149     /**
   1150      * Writes a string to the file using
   1151      * <a href="DataInput.html#modified-utf-8">modified UTF-8</a>
   1152      * encoding in a machine-independent manner.
   1153      * <p>
   1154      * First, two bytes are written to the file, starting at the
   1155      * current file pointer, as if by the
   1156      * {@code writeShort} method giving the number of bytes to
   1157      * follow. This value is the number of bytes actually written out,
   1158      * not the length of the string. Following the length, each character
   1159      * of the string is output, in sequence, using the modified UTF-8 encoding
   1160      * for each character.
   1161      *
   1162      * @param      str   a string to be written.
   1163      * @exception  IOException  if an I/O error occurs.
   1164      */
   1165     public final void writeUTF(String str) throws IOException {
   1166         DataOutputStream.writeUTF(str, this);
   1167     }
   1168 
   1169     @Override protected void finalize() throws Throwable {
   1170         try {
   1171             if (guard != null) {
   1172                 guard.warnIfOpen();
   1173             }
   1174             close();
   1175         } finally {
   1176             super.finalize();
   1177         }
   1178     }
   1179 }
   1180