RandomAccessFile(随机读写流)

RandomAccessFile类既不是输入流InputStream的子类,也不是输出流OutputStream的子类。然而RandomAccessFile创建的流的指向方向既可以作为源,也可以作为目的地。

RandomAccessFile的唯一父类是Object,与其他流父类不同。是用来访问那些保存数据记录的文件的,这样你就可以用seek( )方法来访问记录,并进行读写了。这些记录的大小不必相同;但是其大小和位置必须是可知的。

/*

 *%W% %E%

 *

 *Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.

 *ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.

 */

 

package java.io;

 

import java.nio.channels.FileChannel;

import sun.nio.ch.FileChannelImpl;

 

 

/**

 *Instances of this class support both reading and writing to a

 *random access file. A random access file behaves like a large

 *array of bytes stored in the file system. There is a kind of cursor,

 * orindex into the implied array, called the <em>file pointer</em>;

 *input operations read bytes starting at the file pointer and advance

 *the file pointer past the bytes read. If the random access file is

 *created in read/write mode, then output operations are also available;

 *output operations write bytes starting at the file pointer and advance

 *the file pointer past the bytes written. Output operations that write

 *past the current end of the implied array cause the array to be

 *extended. The file pointer can be read by the

 *<code>getFilePointer</code> method and set by the<code>seek</code>

 *method.

 *<p>

 * Itis generally true of all the reading routines in this class that

 * ifend-of-file is reached before the desired number of bytes has been

 *read, an <code>EOFException</code> (which is a kind of

 *<code>IOException</code>) is thrown. If any byte cannot be read for

 *any reason other than end-of-file, an <code>IOException</code>other

 *than <code>EOFException</code> is thrown. In particular, an

 *<code>IOException</code> may be thrown if the stream has beenclosed.

 *

 *@author  unascribed

 *@version %I%, %G%

 *@since   JDK1.0

 */

 

public class RandomAccessFile implementsDataOutput, DataInput, Closeable {

 

   private FileDescriptor fd;

   private FileChannel channel = null;

   private boolean rw;

 

   private Object closeLock = new Object();

   private volatile boolean closed = false;

 

   private static final int O_RDONLY = 1;

   private static final int O_RDWR =  2;

   private static final int O_SYNC =  4;

   private static final int O_DSYNC = 8;

 

   /**

    * Creates a random access file stream to read from, and optionally

    * to write to, a file with the specified name. A new

    * {@link FileDescriptor} object is created to represent the

    * connection to the file.

    *

    * <p> The <tt>mode</tt> argument specifies the accessmode with which the

    * file is to be opened.  Thepermitted values and their meanings are as

    * specified for the <a

    *href="#mode"><tt>RandomAccessFile(File,String)</tt></a>constructor.

    *

    * <p>

    * If there is a security manager, its <code>checkRead</code>method

    * is called with the <code>name</code> argument

    * as its argument to see if read access to the file is allowed.

    * If the mode allows writing, the security manager's

    * <code>checkWrite</code> method

    * is also called with the <code>name</code> argument

    * as its argument to see if write access to the file is allowed.

    *

    * @param      name   the system-dependent filename

    * @param      mode   the access <ahref="#mode">mode</a>

    * @exception IllegalArgumentException  if themode argument is not equal

    *               to one of<tt>"r"</tt>, <tt>"rw"</tt>,<tt>"rws"</tt>, or

    *              <tt>"rwd"</tt>

    * @exception FileNotFoundException

    *            if the mode is<tt>"r"</tt> but the given string does not

    *            denote an existingregular file, or if the mode begins with

    *           <tt>"rw"</tt> but the given string does not denotean

    *            existing, writableregular file and a new regular file of

    *            that name cannot becreated, or if some other error occurs

    *            while opening orcreating the file

    * @exception SecurityException         if asecurity manager exists and its

    *              <code>checkRead</code> method denies read access to the file

    *               or the mode is"rw" and the security manager's

    *              <code>checkWrite</code> method denies write access to thefile

    * @see       java.lang.SecurityException

    * @see       java.lang.SecurityManager#checkRead(java.lang.String)

    * @see       java.lang.SecurityManager#checkWrite(java.lang.String)

    * @revised 1.4

    * @spec JSR-51

    */

   public RandomAccessFile(String name, String mode)

         throwsFileNotFoundException

    {

       this(name != null ? new File(name) : null, mode);

    }

 

   /**

    * Creates a random access file stream to read from, and optionally to

    * write to, the file specified by the {@link File} argument.  A new {@link

    * FileDescriptor} object is created to represent this file connection.

    *

    * <a name="mode"><p> The <tt>mode</tt>argument specifies the access mode

    * in which the file is to be opened. The permitted values and their

    * meanings are:

    *

    * <blockquote><table summary="Access mode permitted valuesand meanings">

    * <tr><th><palign="left">Value</p></th><th><palign="left">Meaning</p></th></tr>

    * <tr><tdvalign="top"><tt>"r"</tt></td>

    *     <td> Open for readingonly.  Invoking any of the<tt>write</tt>

    *     methods of the resultingobject will cause an {@link

    *     java.io.IOException} to bethrown. </td></tr>

    * <tr><tdvalign="top"><tt>"rw"</tt></td>

    *     <td> Open for readingand writing.  If the file does notalready

    *     exist then an attempt willbe made to create it. </td></tr>

    * <tr><tdvalign="top"><tt>"rws"</tt></td>

    *     <td> Open for readingand writing, as with <tt>"rw"</tt>, and also

    *     require that every update tothe file's content or metadata be

    *     written synchronously to theunderlying storage device. </td></tr>

    * <tr><tdvalign="top"><tt>"rwd"  </tt></td>

    *     <td> Open for readingand writing, as with <tt>"rw"</tt>, and also

    *     require that every update tothe file's content be written

    *     synchronously to theunderlying storage device. </td></tr>

    * </table></blockquote>

    *

    * The <tt>"rws"</tt> and<tt>"rwd"</tt> modes work much like the {@link

    * java.nio.channels.FileChannel#force(boolean) force(boolean)} method of

    * the {@link java.nio.channels.FileChannel} class, passing arguments of

    * <tt>true</tt> and <tt>false</tt>,respectively, except that they always

    * apply to every I/O operation and are therefore often moreefficient.  If

    * the file resides on a local storage device then when an invocation ofa

    * method of this class returns it is guaranteed that all changes made to

    * the file by that invocation will have been written to thatdevice.  This

    * is useful for ensuring that critical information is not lost in the

    * event of a system crash.  If thefile does not reside on a local device

    * then no such guarantee is made.

    *

    * <p> The <tt>"rwd"</tt> mode can be used toreduce the number of I/O

    * operations performed.  Using<tt>"rwd"</tt> only requires updates to the

    * file's content to be written to storage; using<tt>"rws"</tt> requires

    * updates to both the file's content and its metadata to be written,which

    * generally requires at least one more low-level I/O operation.

    *

    * <p> If there is a security manager, its<code>checkRead</code> method is

    * called with the pathname of the <code>file</code> argumentas its

    * argument to see if read access to the file is allowed.  If the mode

    * allows writing, the security manager's<code>checkWrite</code> method is

    * also called with the path argument to see if write access to the fileis

    * allowed.

    *

    * @param      file   the file object

    * @param      mode   the access mode, as described

    *                    <ahref="#mode">above</a>

    * @exception IllegalArgumentException  if themode argument is not equal

    *               to one of<tt>"r"</tt>, <tt>"rw"</tt>,<tt>"rws"</tt>, or

    *              <tt>"rwd"</tt>

    * @exception FileNotFoundException

    *            if the mode is<tt>"r"</tt> but the given file object does

    *            not denote anexisting regular file, or if the mode begins

    *            with<tt>"rw"</tt> but the given file object does not denote

    *            an existing, writableregular file and a new regular file of

    *            that name cannot becreated, or if some other error occurs

    *            while opening orcreating the file

    * @exception SecurityException         if asecurity manager exists and its

    *              <code>checkRead</code> method denies read access to the file

    *               or the mode is"rw" and the security manager's

    *              <code>checkWrite</code> method denies write access to thefile

    * @see       java.lang.SecurityManager#checkRead(java.lang.String)

    * @see        java.lang.SecurityManager#checkWrite(java.lang.String)

    * @see       java.nio.channels.FileChannel#force(boolean)

    * @revised 1.4

    * @spec JSR-51

    */

   public RandomAccessFile(File file, String mode)

         throwsFileNotFoundException

    {

         Stringname = (file != null ? file.getPath() : null);

         intimode = -1;

         if(mode.equals("r"))

             imode = O_RDONLY;

         elseif (mode.startsWith("rw")) {

             imode = O_RDWR;

             rw = true;

             if (mode.length() > 2) {

                   if(mode.equals("rws"))

                       imode |= O_SYNC;

                   elseif (mode.equals("rwd"))

                       imode |= O_DSYNC;

                   else

                       imode = -1;

             }

         }

         if(imode < 0)

             throw newIllegalArgumentException("Illegal mode \"" + mode

                                                      + "\" must be one of "

                                                      + "\"r\",\"rw\", \"rws\","

                                                      + " or \"rwd\"");

         SecurityManagersecurity = System.getSecurityManager();

         if(security != null) {

             security.checkRead(name);

             if (rw) {

                   security.checkWrite(name);

             }

         }

       if (name == null) {

           throw new NullPointerException();

       }

         fd= new FileDescriptor();

       fd.incrementAndGetUseCount();

         open(name,imode);

    }

 

   /**

    * Returns the opaque file descriptor object associated with this

    * stream. </p>

    *

    * @return     the file descriptorobject associated with this stream.

    * @exception  IOException  if an I/O error occurs.

    * @see       java.io.FileDescriptor

    */

   public final FileDescriptor getFD() throws IOException {

         if(fd != null) return fd;

         thrownew IOException();

    }

 

   /**

    * Returns the unique {@link java.nio.channels.FileChannel FileChannel}

    * object associated with this file.

    *

    * <p> The {@link java.nio.channels.FileChannel#position()

    * </code>position<code>} of the returned channel will alwaysbe equal to

    * this object's file-pointer offset as returned by the {@link

    * #getFilePointer getFilePointer} method.  Changing this object's

    * file-pointer offset, whether explicitly or by reading or writingbytes,

    * will change the position of the channel, and vice versa.  Changing the

    * file's length via this object will change the length seen via the file

    * channel, and vice versa.

    *

    * @return  the file channelassociated with this file

    *

    * @since 1.4

    * @spec JSR-51

    */

   public final FileChannel getChannel() {

         synchronized(this) {

             if (channel == null) {

                   channel= FileChannelImpl.open(fd, true, rw, this);

 

                /*

                 * FileDescriptor could beshared by FileInputStream or

                 * FileOutputStream.

                 * Ensure that FD is GC'ed onlywhen all the streams/channels

                 * are done using it.

                 * Increment fd's use count.Invoking the channel's close()

                 * method will result indecrementing the use count set for

                 * the channel.

                 */

                fd.incrementAndGetUseCount();

           }

             return channel;

         }

    }

 

   /**

    * Opens a file and returns the file descriptor.  The file is

    * opened in read-write mode if the O_RDWR bit in<code>mode</code>

    * is true, else the file is opened as read-only.

    * If the <code>name</code> refers to a directory, anIOException

    * is thrown.

    *

    * @param name the name of the file

    * @param mode the mode flags, a combination of the O_ constants

    *             defined above

    */

   private native void open(String name, int mode)

         throwsFileNotFoundException;

 

   // 'Read' primitives

 

   /**

    * Reads a byte of data from this file. The byte is returned as an

    * integer in the range 0 to 255 (<code>0x00-0x0ff</code>).This

    * method blocks if no input is yet available.

    * <p>

    * Although <code>RandomAccessFile</code> is not a subclassof

    * <code>InputStream</code>, this method behaves in exactlythe same

    * way as the {@link InputStream#read()} method of

    * <code>InputStream</code>.

    *

    * @return     the next byte ofdata, or <code>-1</code> if the end of the

    *             file has beenreached.

    * @exception  IOException  if an I/O error occurs. Not thrown if 

    *                         end-of-file has been reached.

    */

   public native int read() throws IOException;

 

   /**

    * Reads a sub array as a sequence of bytes.

    * @param b the buffer into which the data is read.

    * @param off the start offset of the data.

    * @param len the number of bytes to read.

    * @exception IOException If an I/O error has occurred.

    */

   private native int readBytes(byte b[], int off, int len) throwsIOException;

 

   /**

    * Reads up to <code>len</code> bytes of data from this fileinto an

    * array of bytes. This method blocks until at least one byte of input

    * is available.

    * <p>

    * Although <code>RandomAccessFile</code> is not a subclassof

    * <code>InputStream</code>, this method behaves in exactlythe

    * same way as the {@link InputStream#read(byte[], int, int)} method of

    * <code>InputStream</code>.

    *

    * @param      b     the buffer into which the data is read.

    * @param      off   the start offset in array<code>b</code>

    *                   at which the data is written.

    * @param      len   the maximum number of bytes read.

    * @return     the total number ofbytes read into the buffer, or

    *            <code>-1</code> if there is no more data because the end of

    *             the file has been reached.

    * @exception  IOException If thefirst byte cannot be read for any reason

    * other than end of file, or if the random access file has been closed,or if

    * some other I/O error occurs.

    * @exception  NullPointerExceptionIf <code>b</code> is <code>null</code>.

    * @exception IndexOutOfBoundsException If <code>off</code> is negative,

    * <code>len</code> is negative, or<code>len</code> is greater than

    * <code>b.length - off</code>

    */

    public int read(byte b[], int off, int len)throws IOException {

         returnreadBytes(b, off, len);

    }

 

   /**

    * Reads up to <code>b.length</code> bytes of data from thisfile

    * into an array of bytes. This method blocks until at least one byte

    * of input is available.

    * <p>

    * Although <code>RandomAccessFile</code> is not a subclassof

    * <code>InputStream</code>, this method behaves in exactlythe

     * same way as the {@linkInputStream#read(byte[])} method of

    * <code>InputStream</code>.

    *

    * @param      b   the buffer into which the data is read.

    * @return     the total number ofbytes read into the buffer, or

    *             <code>-1</code> if there is nomore data because the end of

    *             this file has beenreached.

    * @exception  IOException If thefirst byte cannot be read for any reason

    * other than end of file, or if the random access file has been closed,or if

    * some other I/O error occurs.

    * @exception  NullPointerExceptionIf <code>b</code> is <code>null</code>.

    */

   public int read(byte b[]) throws IOException {

         returnreadBytes(b, 0, b.length);

    }

 

   /**

    * Reads <code>b.length</code> bytes from this file into thebyte

    * array, starting at the current file pointer. This method reads

    * repeatedly from the file until the requested number of bytes are

    * read. This method blocks until the requested number of bytes are

    * read, the end of the stream is detected, or an exception is thrown.

    *

    * @param      b   the buffer into which the data is read.

    * @exception  EOFException  if this file reaches the end before reading

    *               all the bytes.

    * @exception  IOException   if an I/O error occurs.      

    */

   public final void readFully(byte b[]) throws IOException {

         readFully(b,0, b.length);

    }

 

   /**

    * Reads exactly <code>len</code> bytes from this file intothe byte

    * array, starting at the current file pointer. This method reads

    * repeatedly from the file until the requested number of bytes are

    * read. This method blocks until the requested number of bytes are

    * read, the end of the stream is detected, or an exception is thrown.

    *

    * @param      b     the buffer into which the data is read.

    * @param      off   the start offset of the data.

    * @param      len   the number of bytes to read.

    * @exception  EOFException  if this file reaches the end before reading

    *               all the bytes.

    * @exception  IOException   if an I/O error occurs.

    */

   public final void readFully(byte b[], int off, int len) throwsIOException {

        int n = 0;

         do{

             int count = this.read(b, off + n, len - n);

             if (count < 0)

                   thrownew EOFException();

             n += count;

         }while (n < len);

    }

 

   /**

    * Attempts to skip over <code>n</code> bytes of inputdiscarding the

    * skipped bytes.

    * <p>

    *

    * This method may skip over some smaller number of bytes, possibly zero.

    * This may result from any of a number of conditions; reaching end of

    * file before <code>n</code> bytes have been skipped is onlyone

    * possibility. This method never throws an<code>EOFException</code>.

    * The actual number of bytes skipped is returned.  If <code>n</code>

    * is negative, no bytes are skipped.

    *

    * @param      n   the number of bytes to be skipped.

    * @return     the actual number ofbytes skipped.

    * @exception  IOException  if an I/O error occurs.

    */

   public int skipBytes(int n) throws IOException {

       long pos;

         longlen;

         longnewpos;

 

         if(n <= 0) {

             return 0;

         }

         pos= getFilePointer();

         len= length();

         newpos= pos + n;

         if(newpos > len) {

             newpos = len;

         }

         seek(newpos);

 

         /*return the actual number of bytes skipped */

         return(int) (newpos - pos);

    }

 

   // 'Write' primitives

 

   /**

    * Writes the specified byte to this file. The write starts at

    * the current file pointer.

    *

    * @param      b   the <code>byte</code> to bewritten.

    * @exception  IOException  if an I/O error occurs.

    */

   public native void write(int b) throws IOException;

 

   /**

    * Writes a sub array as a sequence of bytes.

    * @param b the data to be written

 

    * @param off the start offset in the data

    * @param len the number of bytes that are written

    * @exception IOException If an I/O error has occurred.

    */

   private native void writeBytes(byte b[], int off, int len) throwsIOException;

 

   /**

    * Writes <code>b.length</code> bytes from the specified bytearray

    * to this file, starting at the current file pointer.

    *

    * @param      b   the data.

    * @exception  IOException  if an I/O error occurs.

    */

   public void write(byte b[]) throws IOException {

         writeBytes(b,0, b.length);

    }

 

    /**

    * Writes <code>len</code> bytes from the specified bytearray

    * starting at offset <code>off</code> to this file.

    *

    * @param      b     the data.

    * @param      off   the start offset in the data.

    * @param      len   the number of bytes to write.

    * @exception  IOException  if an I/O error occurs.

    */

   public void write(byte b[], int off, int len) throws IOException {

         writeBytes(b,off, len);

    }

 

   // 'Random access' stuff

 

   /**

    * Returns the current offset in this file.

    *

    * @return     the offset from thebeginning of the file, in bytes,

    *             at which the nextread or write occurs.

    * @exception  IOException  if an I/O error occurs.

    */

    publicnative long getFilePointer() throws IOException;

 

   /**

    * Sets the file-pointer offset, measured from the beginning of this

    * file, at which the next read or write occurs.  The offset may be

    * set beyond the end of the file. Setting the offset beyond the end

    * of the file does not change the file length.  The file length will

    * change only by writing after the offset has been set beyond the end

    * of the file.

    *

    * @param      pos   the offset position, measured in bytes fromthe

    *                   beginning ofthe file, at which to set the file

    *                   pointer.

    * @exception  IOException  if <code>pos</code> is less than

    *                         <code>0</code> or if an I/O error occurs.

    */

   public native void seek(long pos) throws IOException;

 

   /**

    * Returns the length of this file.

    *

    * @return     the length of thisfile, measured in bytes.

    * @exception  IOException  if an I/O error occurs.

    */

   public native long length() throws IOException;

 

   /**

    * Sets the length of this file.

    *

    * <p> If the present length of the file as returned by the

    * <code>length</code> method is greater than the<code>newLength</code>

    * argument then the file will be truncated.  In this case, if the file

    * offset as returned by the <code>getFilePointer</code>method is greater

    * than <code>newLength</code> then after this method returnsthe offset

    * will be equal to <code>newLength</code>.

    *

    * <p> If the present length of the file as returned by the

    * <code>length</code> method is smaller than the<code>newLength</code>

    * argument then the file will be extended.  In this case, the contents of

    * the extended portion of the file are not defined.

    *

    * @param      newLength    The desired length of the file

    * @exception  IOException  If an I/O error occurs

     * @since     1.2

    */

   public native void setLength(long newLength) throws IOException;

 

   /**

    * Closes this random access file stream and releases any system

    * resources associated with the stream. A closed random access

    * file cannot perform input or output operations and cannot be

    * reopened.

    *

    * <p> If this file has an associated channel then the channel isclosed

    * as well.

    *

    * @exception  IOException  if an I/O error occurs.

    *

    * @revised 1.4

    * @spec JSR-51

    */

   public void close() throws IOException {

       synchronized (closeLock) {

           if (closed) {

                return;

           }

                closed = true;

       }

       if (channel != null) {

           /*

            * Decrement FD use count associated with the channel. The FD use

            * count is incremented whenever a new channel is obtained from

            * this stream.

            */

           fd.decrementAndGetUseCount();

           channel.close();

       }

 

       /*

        * Decrement FD use count associated with this stream.

        * The count got incremented by FileDescriptor during its construction.

        */

       fd.decrementAndGetUseCount();

       close0();

    }

   

   //

   //  Some "reading/writingJava data types" methods stolen from

   //  DataInputStream andDataOutputStream.

   //

 

   /**

    * Reads a <code>boolean</code> from this file. This methodreads a

    * single byte from the file, starting at the current file pointer.

    * A value of <code>0</code> represents

    * <code>false</code>. Any other value represents<code>true</code>.

    * This method blocks until the byte is read, the end of the stream

    * is detected, or an exception is thrown.

    *

    * @return     the<code>boolean</code> value read.

    * @exception  EOFException  if this file has reached the end.

    * @exception  IOException   if an I/O error occurs.

    */

   public final boolean readBoolean() throws IOException {

         intch = this.read();

         if(ch < 0)

             throw new EOFException();

         return(ch != 0);

    }

 

   /**

    * Reads a signed eight-bit value from this file. This method reads a

    * byte from the file, starting from the current file pointer.

    * If the byte read is <code>b</code>, where

    * <code>0 <= b <= 255</code>,

    * then the result is:

    * <blockquote><pre>

    *     (byte)(b)

    * </pre></blockquote>

     * <p>

    * This method blocks until the byte is read, the end of the stream

    * is detected, or an exception is thrown.

    *

    * @return     the next byte ofthis file as a signed eight-bit

    *            <code>byte</code>.

    * @exception  EOFException  if this file has reached the end.

    * @exception  IOException   if an I/O error occurs.

    */

   public final byte readByte() throws IOException {

         intch = this.read();

         if(ch < 0)

             throw new EOFException();

         return(byte)(ch);

    }

 

   /**

    * Reads an unsigned eight-bit number from this file. This method reads

    * a byte from this file, starting at the current file pointer,

    * and returns that byte.

    * <p>

    * This method blocks until the byte is read, the end of the stream

    * is detected, or an exception is thrown.

    *

    * @return     the next byte ofthis file, interpreted as an unsigned

    *             eight-bit number.

    * @exception  EOFException  if this file has reached the end.

    * @exception  IOException   if an I/O error occurs.

    */

   public final int readUnsignedByte() throws IOException {

         intch = this.read();

         if(ch < 0)

             throw new EOFException();

         returnch;

    }

 

   /**

    * Reads a signed 16-bit number from this file. The method reads two

    * bytes from this file, starting at the current file pointer.

    * If the two bytes read, in order, are

    * <code>b1</code> and <code>b2</code>, whereeach of the two values is

    * between <code>0</code> and <code>255</code>,inclusive, then the

    * result is equal to:

    * <blockquote><pre>

    *     (short)((b1 << 8) |b2)

    * </pre></blockquote>

    * <p>

    * This method blocks until the two bytes are read, the end of the

    * stream is detected, or an exception is thrown.

    *

    * @return     the next two bytesof this file, interpreted as a signed

    *             16-bit number.

    * @exception  EOFException  if this file reaches the end before reading

    *               two bytes.

    * @exception  IOException   if an I/O error occurs.

    */

   public final short readShort() throws IOException {

         intch1 = this.read();

         intch2 = this.read();

         if((ch1 | ch2) < 0)

             throw new EOFException();

         return(short)((ch1 << 8) + (ch2 << 0));

    }

 

   /**

    * Reads an unsigned 16-bit number from this file. This method reads

    * two bytes from the file, starting at the current file pointer.

    * If the bytes read, in order, are

    * <code>b1</code> and <code>b2</code>, where

    * <code>0 <= b1, b2 <= 255</code>,

    * then the result is equal to:

    * <blockquote><pre>

    *     (b1 << 8) | b2

    * </pre></blockquote>

    * <p>

    * This method blocks until the two bytes are read, the end of the

    * stream is detected, or an exception is thrown.

    *

    * @return     the next two bytesof this file, interpreted as an unsigned

    *             16-bit integer.

    * @exception  EOFException  if this file reaches the end before reading

    *               two bytes.

    * @exception  IOException   if an I/O error occurs.

    */

   public final int readUnsignedShort() throws IOException {

         intch1 = this.read();

         intch2 = this.read();

         if((ch1 | ch2) < 0)

             throw new EOFException();

         return(ch1 << 8) + (ch2 << 0);

    }

 

   /**

    * Reads a character from this file. This method reads two

    * bytes from the file, starting at the current file pointer.

    * If the bytes read, in order, are

    * <code>b1</code> and <code>b2</code>, where

    * <code>0 <= b1, b2 <= 255</code>,

    * then the result is equal to:

    * <blockquote><pre>

    *     (char)((b1 << 8) | b2)

    * </pre></blockquote>

    * <p>

    * This method blocks until the two bytes are read, the end of the

    * stream is detected, or an exception is thrown.

    *

    * @return     the next two bytesof this file, interpreted as a

    *                 <code>char</code>.

    * @exception  EOFException  if this file reaches the end before reading

    *               two bytes.

    * @exception  IOException   if an I/O error occurs.

    */

   public final char readChar() throws IOException {

         intch1 = this.read();

         intch2 = this.read();

         if((ch1 | ch2) < 0)

             throw new EOFException();

         return(char)((ch1 << 8) + (ch2 << 0));

    }

 

   /**

    * Reads a signed 32-bit integer from this file. This method reads 4

    * bytes from the file, starting at the current file pointer.

    * If the bytes read, in order, are <code>b1</code>,

    * <code>b2</code>, <code>b3</code>, and<code>b4</code>, where

    * <code>0 <= b1, b2, b3, b4 <= 255</code>,

    * then the result is equal to:

     * <blockquote><pre>

    *     (b1 << 24) | (b2<< 16) + (b3 << 8) + b4

    * </pre></blockquote>

    * <p>

    * This method blocks until the four bytes are read, the end of the

    * stream is detected, or an exception is thrown.

    *

    * @return     the next four bytesof this file, interpreted as an

    *            <code>int</code>.

    * @exception  EOFException  if this file reaches the end before reading

    *               four bytes.

    * @exception  IOException   if an I/O error occurs.

    */

   public final int readInt() throws IOException {

         intch1 = this.read();

         intch2 = this.read();

         intch3 = this.read();

         intch4 = this.read();

         if((ch1 | ch2 | ch3 | ch4) < 0)

             throw new EOFException();

         return((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));

    }

 

   /**

    * Reads a signed 64-bit integer from this file. This method reads eight

    * bytes from the file, starting at the current file pointer.

    * If the bytes read, in order, are

    * <code>b1</code>, <code>b2</code>,<code>b3</code>,

    * <code>b4</code>, <code>b5</code>,<code>b6</code>,

    * <code>b7</code>, and <code>b8,</code> where:

    * <blockquote><pre>

    *     0 <= b1, b2, b3, b4, b5,b6, b7, b8 <=255,

    * </pre></blockquote>

    * <p>

    * then the result is equal to:

    * <p><blockquote><pre>

    *     ((long)b1 << 56) +((long)b2 << 48)

    *     + ((long)b3 << 40) +((long)b4 << 32)

    *     + ((long)b5 << 24) +((long)b6 << 16)

    *     + ((long)b7 << 8) + b8

    * </pre></blockquote>

    * <p>

    * This method blocks until the eight bytes are read, the end of the

    * stream is detected, or an exception is thrown.

    *

    * @return     the next eight bytesof this file, interpreted as a

    *            <code>long</code>.

    * @exception  EOFException  if this file reaches the end before reading

    *               eight bytes.

    * @exception  IOException   if an I/O error occurs.

    */

   public final long readLong() throws IOException {

         return((long)(readInt()) << 32) + (readInt() & 0xFFFFFFFFL);

    }

 

   /**

    * Reads a <code>float</code> from this file. This methodreads an

    * <code>int</code> value, starting at the current filepointer,

    * as if by the <code>readInt</code> method

    * and then converts that <code>int</code> to a<code>float</code>

    * using the <code>intBitsToFloat</code> method in class

    * <code>Float</code>.

    * <p>

    * This method blocks until the four bytes are read, the end of the

    * stream is detected, or an exception is thrown.

    *

    * @return     the next four bytesof this file, interpreted as a

    *            <code>float</code>.

    * @exception  EOFException  if this file reaches the end before reading

    *             four bytes.

    * @exception  IOException   if an I/O error occurs.

    * @see       java.io.RandomAccessFile#readInt()

    * @see       java.lang.Float#intBitsToFloat(int)

    */

   public final float readFloat() throws IOException {

         returnFloat.intBitsToFloat(readInt());

    }

 

   /**

    * Reads a <code>double</code> from this file. This methodreads a

    * <code>long</code> value, starting at the current filepointer,

    * as if by the <code>readLong</code> method

    * and then converts that <code>long</code> to a<code>double</code>

    * using the <code>longBitsToDouble</code> method in

    * class <code>Double</code>.

    * <p>

    * This method blocks until the eight bytes are read, the end of the

    * stream is detected, or an exception is thrown.

    *

    * @return     the next eight bytesof this file, interpreted as a

    *             <code>double</code>.

    * @exception  EOFException  if this file reaches the end before reading

    *             eight bytes.

    * @exception  IOException   if an I/O error occurs.

    * @see       java.io.RandomAccessFile#readLong()

    * @see       java.lang.Double#longBitsToDouble(long)

    */

   public final double readDouble() throws IOException {

         returnDouble.longBitsToDouble(readLong());

    }

 

   /**

    * Reads the next line of text from this file.  This method successively

    * reads bytes from the file, starting at the current file pointer,

    * until it reaches a line terminator or the end

    * of the file.  Each byte isconverted into a character by taking the

    * byte's value for the lower eight bits of the character and setting the

    * high eight bits of the character to zero.  This method does not,

    * therefore, support the full Unicode character set.

    *

    * <p> A line of text is terminated by a carriage-return character

    * (<code>'\r'</code>), a newline character(<code>'\n'</code>), a

    * carriage-return character immediately followed by a newline character,

    * or the end of the file. Line-terminating characters are discarded and

    * are not included as part of the string returned.

    *

    * <p> This method blocks until a newline character is read, acarriage

    * return and the byte following it are read (to see if it is a newline),

    * the end of the file is reached, or an exception is thrown.

    *

    * @return     the next line oftext from this file, or null if end

    *             of file isencountered before even one byte is read.

    * @exception  IOException  if an I/O error occurs.

    */

 

   public final String readLine() throws IOException {

         StringBufferinput = new StringBuffer();

         intc = -1;

         booleaneol = false;

 

         while(!eol) {

             switch (c = read()) {

             case -1:

             case '\n':

                   eol= true;

                   break;

             case '\r':

                   eol= true;

                   longcur = getFilePointer();

                   if((read()) != '\n') {

                       seek(cur);

                   }

                   break;

             default:

                   input.append((char)c);

                   break;

             }

         }

 

         if((c == -1) && (input.length() == 0)) {

             return null;

         }

         returninput.toString();

    }

 

   /**

    * Reads in a string from this file. The string has been encoded

    * using a

    * <a href="DataInput.html#modified-utf-8">modifiedUTF-8</a>

    * format.

    * <p>

    * The first two bytes are read, starting from the current file

    * pointer, as if by

    * <code>readUnsignedShort</code>. This value gives thenumber of

    * following bytes that are in the encoded string, not

    * the length of the resulting string. The following bytes are then

    * interpreted as bytes encoding characters in the modified UTF-8 format

    * and are converted into characters.

    * <p>

    * This method blocks until all the bytes are read, the end of the

    * stream is detected, or an exception is thrown.

    *

    * @return     a Unicode string.

    * @exception  EOFException            if this file reaches the end before

    *               reading all thebytes.

    * @exception  IOException             if an I/O error occurs.

    * @exception UTFDataFormatException  if thebytes do not represent

    *               valid modifiedUTF-8 encoding of a Unicode string.

    * @see       java.io.RandomAccessFile#readUnsignedShort()

    */

   public final String readUTF() throws IOException {

         returnDataInputStream.readUTF(this);

    }

 

   /**

    * Writes a <code>boolean</code> to the file as a one-bytevalue. The

    * value <code>true</code> is written out as the value

    * <code>(byte)1</code>; the value<code>false</code> is written out

    * as the value <code>(byte)0</code>. The write starts at

    * the current position of the file pointer.

    *

    * @param      v   a <code>boolean</code> value tobe written.

    * @exception  IOException  if an I/O error occurs.

    */

   public final void writeBoolean(boolean v) throws IOException {

         write(v? 1 : 0);

         //written++;

    }

 

   /**

    * Writes a <code>byte</code> to the file as a one-bytevalue. The

    * write starts at the current position of the file pointer.

    *

     * @param     v   a<code>byte</code> value to be written.

    * @exception  IOException  if an I/O error occurs.

    */

   public final void writeByte(int v) throws IOException {

         write(v);

         //written++;

    }

 

   /**

    * Writes a <code>short</code> to the file as two bytes, highbyte first.

    * The write starts at the current position of the file pointer.

    *

    * @param      v   a <code>short</code> to bewritten.

    * @exception  IOException  if an I/O error occurs.

    */

   public final void writeShort(int v) throws IOException {

         write((v>>> 8) & 0xFF);

         write((v>>> 0) & 0xFF);

         //written+= 2;

    }

 

   /**

    * Writes a <code>char</code> to the file as a two-bytevalue, high

    * byte first. The write starts at the current position of the

    * file pointer.

    *

    * @param      v   a <code>char</code> value to bewritten.

    * @exception  IOException  if an I/O error occurs.

    */

   public final void writeChar(int v) throws IOException {

         write((v>>> 8) & 0xFF);

         write((v>>> 0) & 0xFF);

         //written+= 2;

    }

 

   /**

    * Writes an <code>int</code> to the file as four bytes, highbyte first.

    * The write starts at the current position of the file pointer.

    *

    * @param      v   an <code>int</code> to bewritten.

    * @exception  IOException  if an I/O error occurs.

    */

   public final void writeInt(int v) throws IOException {

         write((v>>> 24) & 0xFF);

         write((v>>> 16) & 0xFF);

         write((v>>>  8) & 0xFF);

         write((v>>>  0) & 0xFF);

         //written+= 4;

    }

 

   /**

    * Writes a <code>long</code> to the file as eight bytes,high byte first.

    * The write starts at the current position of the file pointer.

    *

    * @param      v   a <code>long</code> to bewritten.

    * @exception  IOException  if an I/O error occurs.

    */

   public final void writeLong(long v) throws IOException {

         write((int)(v>>> 56) & 0xFF);

         write((int)(v>>> 48) & 0xFF);

         write((int)(v>>> 40) & 0xFF);

         write((int)(v>>> 32) & 0xFF);

         write((int)(v>>> 24) & 0xFF);

         write((int)(v>>> 16) & 0xFF);

         write((int)(v>>>  8) & 0xFF);

         write((int)(v>>>  0) & 0xFF);

         //written+= 8;

    }

 

   /**

    * Converts the float argument to an <code>int</code> usingthe

    * <code>floatToIntBits</code> method in class<code>Float</code>,

    * and then writes that <code>int</code> value to the file asa

    * four-byte quantity, high byte first. The write starts at the

    * current position of the file pointer.

     *

    * @param      v   a <code>float</code> value to bewritten.

    * @exception  IOException  if an I/O error occurs.

    * @see       java.lang.Float#floatToIntBits(float)

    */

   public final void writeFloat(float v) throws IOException {

         writeInt(Float.floatToIntBits(v));

    }

 

   /**

    * Converts the double argument to a <code>long</code> usingthe

    * <code>doubleToLongBits</code> method in class<code>Double</code>,

    * and then writes that <code>long</code> value to the fileas an

    * eight-byte quantity, high byte first. The write starts at the current

    * position of the file pointer.

    *

    * @param      v   a <code>double</code> value tobe written.

    * @exception  IOException  if an I/O error occurs.

     * @see       java.lang.Double#doubleToLongBits(double)

    */

   public final void writeDouble(double v) throws IOException {

         writeLong(Double.doubleToLongBits(v));

    }

 

   /**

    * Writes the string to the file as a sequence of bytes. Each

    * character in the string is written out, in sequence, by discarding

    * its high eight bits. The write starts at the current position of

    * the file pointer.

    *

    * @param      s   a string of bytes to be written.

    * @exception  IOException  if an I/O error occurs.

    */

   public final void writeBytes(String s) throws IOException {

         intlen = s.length();

         byte[]b = new byte[len];

         s.getBytes(0,len, b, 0);

         writeBytes(b,0, len);

    }

 

   /**

    * Writes a string to the file as a sequence of characters. Each

    * character is written to the data output stream as if by the

    * <code>writeChar</code> method. The write starts at thecurrent

    * position of the file pointer.

    *

    * @param      s   a <code>String</code> value tobe written.

    * @exception  IOException  if an I/O error occurs.

    * @see       java.io.RandomAccessFile#writeChar(int)

    */

   public final void writeChars(String s) throws IOException {

         intclen = s.length();

         intblen = 2*clen;

         byte[]b = new byte[blen];

         char[]c = new char[clen];

         s.getChars(0,clen, c, 0);

         for(int i = 0, j = 0; i < clen; i++) {

             b[j++] = (byte)(c[i] >>> 8);

             b[j++] = (byte)(c[i] >>> 0);

         }

         writeBytes(b,0, blen);

    }

 

   /**

    * Writes a string to the file using

    * <a href="DataInput.html#modified-utf-8">modifiedUTF-8</a>

    * encoding in a machine-independent manner.

    * <p>

    * First, two bytes are written to the file, starting at the

    * current file pointer, as if by the

    * <code>writeShort</code> method giving the number of bytesto

    * follow. This value is the number of bytes actually written out,

    * not the length of the string. Following the length, each character

    * of the string is output, in sequence, using the modified UTF-8encoding

    * for each character.

    *

    * @param      str   a string to be written.

    * @exception  IOException  if an I/O error occurs.

    */

   public final void writeUTF(String str) throws IOException {

       DataOutputStream.writeUTF(str, this);

    }

 

   private static native void initIDs();

 

   private native void close0() throws IOException;

 

   static {

         initIDs();

    }

 

}

 

 

基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream粘起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )。

DataOutput 接口用于将数据从任意 Java 基本类型转换为一系列字节,并将这些字节写入二进制流。同时还提供了一个将 String 转换成 UTF-8格式并写入所得到的系列字节的工具。

RandomAccessFile

 

public RandomAccessFile(File file,

                        String mode)

                 throws FileNotFoundException

创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。将创建一个新的 FileDescriptor 对象来表示此文件的连接。

mode 参数指定用以打开文件的访问模式。

"r"    以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。

"rw"          打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。

"rws"        打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。(适合移动设备上的断点文件下载)

"rwd"     打开以便读取和写入,对于"rw",还要求对文件内容的每个更新都同步写入到底层存储设备。(适合移动设备上的断点文件下载)

我实现多线程断点下载的方法基本就是借用RandomAccessFile类,从而构建出需要的对象。

 

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值