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