You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by nd...@apache.org on 2006/08/18 03:45:39 UTC

svn commit: r432462 [19/21] - /incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/

Modified: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/RandomAccessFile.java
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/RandomAccessFile.java?rev=432462&r1=432461&r2=432462&view=diff
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/RandomAccessFile.java (original)
+++ incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/RandomAccessFile.java Thu Aug 17 18:45:35 2006
@@ -1,1036 +1,1036 @@
-/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- *     http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package java.io;
-
-import java.nio.channels.FileChannel;
-
-import org.apache.harmony.luni.platform.IFileSystem;
-import org.apache.harmony.luni.platform.Platform;
-import org.apache.harmony.luni.util.Msg;
-import org.apache.harmony.luni.util.Util;
-
-import org.apache.harmony.nio.FileChannelFactory;
-
-/**
- * RandomAccessFile is a class which allows positioning of the next read
- * anywhere in the file. This is useful for reading specific locations of files
- * or following links within a file. Most input classes only support forward
- * skipping.
- */
-public class RandomAccessFile implements DataInput, DataOutput, Closeable {
-    /**
-     * The FileDescriptor representing this RandomAccessFile.
-     */
-    private FileDescriptor fd;
-
-    private boolean syncMetadata = false;
-
-    // The unique file channel associated with this FileInputStream (lazily
-    // initialized).
-    private FileChannel channel;
-
-    private IFileSystem fileSystem = Platform.getFileSystem();
-
-    private boolean isReadOnly;
-
-    private Object repositionLock = new Object();
-
-    /**
-     * Constructs a new RandomAccessFile on the File <code>file</code> and
-     * opens it according to the access String in <code>mode</code>. The
-     * access mode may be one of <code>"r"</code> for read access only, or
-     * <code>"rw"</code> for read/write access.
-     * 
-     * @param file
-     *            the File to open.
-     * @param mode
-     *            "r" for read only, or "rw" for read/write.
-     * 
-     * @throws FileNotFoundException
-     *             If the <code>mode</code> is incorrect or the File cannot be
-     *             opened in the requested <code>mode</code>.
-     * 
-     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
-     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
-     */
-    public RandomAccessFile(File file, String mode)
-            throws FileNotFoundException {
-        super();
-
-        int options = 0;
-
-        if (mode.equals("r")) { //$NON-NLS-1$
-            isReadOnly = true;
-            options = IFileSystem.O_RDONLY;
-        } else if (mode.equals("rw") || mode.equals("rws") || mode.equals("rwd")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-            isReadOnly = false;
-            options = IFileSystem.O_RDWR;
-
-            if (mode.equals("rws")) { //$NON-NLS-1$
-                // Sync file and metadata with every write
-                syncMetadata = true;
-            } else if (mode.equals("rwd")) { //$NON-NLS-1$
-                // Sync file, but not necessarily metadata
-                options = IFileSystem.O_RDWRSYNC;
-            }
-
-        } else {
-            throw new IllegalArgumentException(Msg.getString("K0081")); //$NON-NLS-1$
-        }
-
-        SecurityManager security = System.getSecurityManager();
-        if (security != null) {
-            security.checkRead(file.getPath());
-            if (!isReadOnly) {
-                security.checkWrite(file.getPath());
-            }
-        }
-
-        fd = new FileDescriptor();
-        fd.descriptor = fileSystem.open(file.properPath(true), options);
-        channel = FileChannelFactory.getFileChannel(this, fd.descriptor,
-                options);
-
-        // if we are in "rws" mode, attempt to sync file+metadata
-        if (syncMetadata) {
-            try {
-                fd.sync();
-            } catch (IOException e) {
-            }
-        }
-    }
-
-    /**
-     * Constructs a new RandomAccessFile on the file named <code>fileName</code>
-     * and opens it according to the access String in <code>mode</code>. The
-     * file may be absolute or relative to the System property
-     * <code>"user.dir"</code>. The access mode may be one of
-     * <code>"r"</code> for read access only, or <code>"rw"</code> for
-     * read/write access.
-     * 
-     * 
-     * @param fileName
-     *            the filename of the file to open.
-     * @param mode
-     *            "r" for read only, or "rw" for read/write.
-     * 
-     * @throws FileNotFoundException
-     *             If the <code>mode</code> is incorrect or the file cannot be
-     *             opened in the requested <code>mode</code>.
-     * 
-     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
-     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
-     */
-    public RandomAccessFile(String fileName, String mode)
-            throws FileNotFoundException {
-        this(new File(fileName), mode);
-    }
-
-    /**
-     * Close this RandomAccessFile.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to close this RandomAccessFile.
-     */
-    public void close() throws IOException {
-        synchronized (channel) {
-            synchronized (this) {
-                if (channel.isOpen() && fd.descriptor >= 0) {
-                    channel.close();
-                }
-                fd.descriptor = -1;
-            }
-        }
-    }
-
-    /**
-     * Answers the FileChannel equivalent to this stream.
-     * <p>
-     * The file channel is write-only and has an initial position within the
-     * file that is the same as the current position of this FileOutputStream
-     * within the file. All changes made to the underlying file descriptor state
-     * via the channel are visible by the output stream and vice versa.
-     * </p>
-     * 
-     * @return the file channel representation for this FileOutputStream.
-     */
-    public final synchronized FileChannel getChannel() {
-        return channel;
-    }
-
-    /**
-     * Answers the FileDescriptor representing the operating system resource for
-     * this RandomAccessFile.
-     * 
-     * @return the FileDescriptor for this RandomAccessFile.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to get the FileDescriptor of
-     *             this RandomAccessFile.
-     */
-    public final FileDescriptor getFD() throws IOException {
-        return fd;
-    }
-
-    /**
-     * Answers the current position within this RandomAccessFile. All reads and
-     * writes take place at the current file pointer position.
-     * 
-     * @return the current file pointer position.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to get the file pointer
-     *             position of this RandomAccessFile.
-     */
-    public long getFilePointer() throws IOException {
-        openCheck();
-        return fileSystem.seek(fd.descriptor, 0L, IFileSystem.SEEK_CUR);
-    }
-
-    private synchronized void openCheck() throws IOException {
-        if (fd.descriptor < 0) {
-            throw new IOException();
-        }
-    }
-
-    /**
-     * Answers the current length of this RandomAccessFile in bytes.
-     * 
-     * @return the current file length in bytes.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to get the file length of this
-     *             RandomAccessFile.
-     */
-    public long length() throws IOException {
-        openCheck();
-        synchronized (repositionLock) {
-            long currentPosition = fileSystem.seek(fd.descriptor, 0L,
-                    IFileSystem.SEEK_CUR);
-            long endOfFilePosition = fileSystem.seek(fd.descriptor, 0L,
-                    IFileSystem.SEEK_END);
-            fileSystem.seek(fd.descriptor, currentPosition,
-                    IFileSystem.SEEK_SET);
-            return endOfFilePosition;
-        }
-    }
-
-    /**
-     * Reads a single byte from this RandomAccessFile and returns the result as
-     * an int. The low-order byte is returned or -1 of the end of file was
-     * encountered.
-     * 
-     * @return the byte read or -1 if end of file.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to read from this
-     *             RandomAccessFile.
-     * 
-     * @see #write(byte[])
-     * @see #write(byte[], int, int)
-     * @see #write(int)
-     */
-    public int read() throws IOException {
-        openCheck();
-        byte[] bytes = new byte[1];
-        synchronized (repositionLock) {
-            long readed = fileSystem.read(fd.descriptor, bytes, 0, 1);
-            return readed == -1 ? -1 : bytes[0] & 0xff;
-        }
-    }
-
-    /**
-     * Reads bytes from this RandomAccessFile into the byte array
-     * <code>buffer</code>. The number of bytes actually read is returned.
-     * 
-     * @param buffer
-     *            the buffer to read bytes into
-     * @return the number of bytes actually read or -1 if end of file.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to read from this
-     *             RandomAccessFile.
-     * 
-     * @see #write(byte[])
-     * @see #write(byte[], int, int)
-     * @see #write(int)
-     */
-    public int read(byte[] buffer) throws IOException {
-        return read(buffer, 0, buffer.length);
-    }
-
-    /**
-     * Reads at most <code>count</code> bytes from this RandomAccessFile and
-     * stores them in byte array <code>buffer</code> starting at
-     * <code>offset</code>. Answer the number of bytes actually read or -1 if
-     * no bytes were read and end of file was encountered.
-     * 
-     * @param buffer
-     *            the byte array in which to store the read bytes.
-     * @param offset
-     *            the offset in <code>buffer</code> to store the read bytes.
-     * @param count
-     *            the maximum number of bytes to store in <code>buffer</code>.
-     * @return the number of bytes actually read or -1 if end of file.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to read from this
-     *             RandomAccessFile.
-     * 
-     * @see #write(byte[])
-     * @see #write(byte[], int, int)
-     * @see #write(int)
-     */
-    public int read(byte[] buffer, int offset, int count) throws IOException {
-        // have to have four comparisions to not miss integer overflow cases
-        if (count > buffer.length - offset || count < 0 || offset < 0) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (0 == count) {
-            return 0;
-        }
-        openCheck();
-        synchronized (repositionLock) {
-            return (int) fileSystem.read(fd.descriptor, buffer, offset, count);
-        }
-    }
-
-    /**
-     * Reads a boolean from this stream.
-     * 
-     * @return boolean the next boolean value from the source stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeBoolean(boolean)
-     */
-    public final boolean readBoolean() throws IOException {
-        int temp = this.read();
-        if (temp >= 0) {
-            return temp != 0;
-        }
-        throw new EOFException();
-    }
-
-    /**
-     * Reads an 8-bit byte value from this stream.
-     * 
-     * @return byte the next byte value from the source stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeByte(int)
-     */
-    public final byte readByte() throws IOException {
-        int temp = this.read();
-        if (temp >= 0) {
-            return (byte) temp;
-        }
-        throw new EOFException();
-    }
-
-    /**
-     * Reads a 16-bit character value from this stream.
-     * 
-     * @return char the next <code>char</code> value from the source stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeChar(int)
-     */
-    public final char readChar() throws IOException {
-        byte[] buffer = new byte[2];
-        if (read(buffer, 0, buffer.length) == buffer.length) {
-            return (char) (((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff));
-        }
-        throw new EOFException();
-    }
-
-    /**
-     * Reads a 64-bit <code>double</code> value from this stream.
-     * 
-     * @return double the next <code>double</code> value from the source
-     *         stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeDouble(double)
-     */
-    public final double readDouble() throws IOException {
-        return Double.longBitsToDouble(readLong());
-    }
-
-    /**
-     * Reads a 32-bit <code>float</code> value from this stream.
-     * 
-     * @return float the next <code>float</code> value from the source stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeFloat(float)
-     */
-    public final float readFloat() throws IOException {
-        return Float.intBitsToFloat(readInt());
-    }
-
-    /**
-     * Reads bytes from this stream into the byte array <code>buffer</code>.
-     * This method will block until <code>buffer.length</code> number of bytes
-     * have been read.
-     * 
-     * @param buffer
-     *            the buffer to read bytes into
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#write(byte[])
-     * @see DataOutput#write(byte[], int, int)
-     */
-    public final void readFully(byte[] buffer) throws IOException {
-        readFully(buffer, 0, buffer.length);
-    }
-
-    /**
-     * Read bytes from this stream and stores them in byte array
-     * <code>buffer</code> starting at offset <code>offset</code>. This
-     * method blocks until <code>count</code> number of bytes have been read.
-     * 
-     * @param buffer
-     *            the byte array in which to store the read bytes.
-     * @param offset
-     *            the offset in <code>buffer</code> to store the read bytes.
-     * @param count
-     *            the maximum number of bytes to store in <code>buffer</code>.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#write(byte[])
-     * @see DataOutput#write(byte[], int, int)
-     */
-    public final void readFully(byte[] buffer, int offset, int count)
-            throws IOException {
-        if (buffer != null) {
-            // avoid int overflow
-            if (0 <= offset && offset <= buffer.length && 0 <= count
-                    && count <= buffer.length - offset) {
-                while (count > 0) {
-                    int result = read(buffer, offset, count);
-                    if (result >= 0) {
-                        offset += result;
-                        count -= result;
-                    } else {
-                        throw new EOFException();
-                    }
-                }
-            } else {
-                throw new IndexOutOfBoundsException();
-            }
-        } else {
-            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
-        }
-    }
-
-    /**
-     * Reads a 32-bit integer value from this stream.
-     * 
-     * @return int the next <code>int</code> value from the source stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeInt(int)
-     */
-    public final int readInt() throws IOException {
-        byte[] buffer = new byte[4];
-        if (read(buffer, 0, buffer.length) == buffer.length) {
-            return ((buffer[0] & 0xff) << 24) + ((buffer[1] & 0xff) << 16)
-                    + ((buffer[2] & 0xff) << 8) + (buffer[3] & 0xff);
-        }
-        throw new EOFException();
-    }
-
-    /**
-     * Answers a <code>String</code> representing the next line of text
-     * available in this BufferedReader. A line is represented by 0 or more
-     * characters followed by <code>'\n'</code>, <code>'\r'</code>,
-     * <code>"\n\r"</code> or end of stream. The <code>String</code> does
-     * not include the newline sequence.
-     * 
-     * @return String the contents of the line or null if no characters were
-     *         read before end of stream.
-     * 
-     * @throws IOException
-     *             If the BufferedReader is already closed or some other IO
-     *             error occurs.
-     */
-    public final String readLine() throws IOException {
-        StringBuilder line = new StringBuilder(80); // Typical line length
-        boolean foundTerminator = false;
-        long unreadPosition = 0;
-        while (true) {
-            int nextByte = read();
-            switch (nextByte) {
-                case -1:
-                    return line.length() != 0 ? line.toString() : null;
-                case (byte) '\r':
-                    if (foundTerminator) {
-                        seek(unreadPosition);
-                        return line.toString();
-                    }
-                    foundTerminator = true;
-                    /* Have to be able to peek ahead one byte */
-                    unreadPosition = getFilePointer();
-                    break;
-                case (byte) '\n':
-                    return line.toString();
-                default:
-                    if (foundTerminator) {
-                        seek(unreadPosition);
-                        return line.toString();
-                    }
-                    line.append((char) nextByte);
-            }
-        }
-    }
-
-    /**
-     * Reads a 64-bit <code>long</code> value from this stream.
-     * 
-     * @return long the next <code>long</code> value from the source stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeLong(long)
-     */
-    public final long readLong() throws IOException {
-        byte[] buffer = new byte[8];
-        if (read(buffer, 0, buffer.length) == buffer.length) {
-            return ((long) (((buffer[0] & 0xff) << 24)
-                    + ((buffer[1] & 0xff) << 16) + ((buffer[2] & 0xff) << 8) + (buffer[3] & 0xff)) << 32)
-                    + ((long) (buffer[4] & 0xff) << 24)
-                    + ((buffer[5] & 0xff) << 16)
-                    + ((buffer[6] & 0xff) << 8)
-                    + (buffer[7] & 0xff);
-        }
-        throw new EOFException();
-    }
-
-    /**
-     * Reads a 16-bit <code>short</code> value from this stream.
-     * 
-     * @return short the next <code>short</code> value from the source stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeShort(int)
-     */
-    public final short readShort() throws IOException {
-        byte[] buffer = new byte[2];
-        if (read(buffer, 0, buffer.length) == buffer.length) {
-            return (short) (((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff));
-        }
-        throw new EOFException();
-    }
-
-    /**
-     * Reads an unsigned 8-bit <code>byte</code> value from this stream and
-     * returns it as an int.
-     * 
-     * @return int the next unsigned byte value from the source stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeByte(int)
-     */
-    public final int readUnsignedByte() throws IOException {
-        int temp = this.read();
-        if (temp >= 0) {
-            return temp;
-        }
-        throw new EOFException();
-    }
-
-    /**
-     * Reads a 16-bit unsigned <code>short</code> value from this stream and
-     * returns it as an int.
-     * 
-     * @return int the next unsigned <code>short</code> value from the source
-     *         stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeShort(int)
-     */
-    public final int readUnsignedShort() throws IOException {
-        byte[] buffer = new byte[2];
-        if (read(buffer, 0, buffer.length) == buffer.length) {
-            return ((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff);
-        }
-        throw new EOFException();
-    }
-
-    /**
-     * Reads a UTF format String from this Stream.
-     * 
-     * @return String the next UTF String from the source stream.
-     * 
-     * @throws IOException
-     *             If a problem occurs reading from this DataInputStream.
-     * 
-     * @see DataOutput#writeUTF(java.lang.String)
-     */
-    public final String readUTF() throws IOException {
-        int utfSize = readUnsignedShort();
-        if (utfSize == 0) {
-            return new String();
-        }
-        byte[] buf = new byte[utfSize];
-        if (read(buf, 0, buf.length) == buf.length) {
-            return Util.convertFromUTF8(buf, 0, utfSize);
-        }
-        throw new EOFException();
-    }
-
-    /**
-     * Seeks to the position <code>pos</code> in this RandomAccessFile. All
-     * read/write/skip methods sent will be relative to <code>pos</code>.
-     * 
-     * @param pos
-     *            the desired file pointer position
-     * 
-     * @throws IOException
-     *             If the stream is already closed or another IOException
-     *             occurs.
-     */
-    public void seek(long pos) throws IOException {
-        if (pos < 0) {
-            // seek position is negative
-            throw new IOException(Msg.getString("K0347")); //$NON-NLS-1$
-        }
-        openCheck();
-        synchronized (repositionLock) {
-            fileSystem.seek(fd.descriptor, pos, IFileSystem.SEEK_SET);
-        }
-    }
-
-    /**
-     * Set the length of this file to be <code>newLength</code>. If the
-     * current file is smaller, it will be expanded and the filePosition will be
-     * set to the new file length. If the <code>newLength</code> is smaller
-     * then the file will be truncated.
-     * 
-     * @param newLength
-     *            the desired file length
-     * 
-     * @throws IOException
-     *             If the stream is already closed or another IOException
-     *             occurs.
-     */
-    public void setLength(long newLength) throws IOException {
-        openCheck();
-        if (newLength < 0) {
-            throw new IllegalArgumentException();
-        }
-        synchronized (repositionLock) {
-            long position = fileSystem.seek(fd.descriptor, 0,
-                    IFileSystem.SEEK_CUR);
-            fileSystem.truncate(fd.descriptor, newLength);
-            seek(position > newLength ? newLength : position);
-        }
-
-        // if we are in "rws" mode, attempt to sync file+metadata
-        if (syncMetadata) {
-            fd.sync();
-        }
-    }
-
-    /**
-     * Skips <code>count</code> number of bytes in this stream. Subsequent
-     * <code>read()</code>'s will not return these bytes unless
-     * <code>reset()</code> is used.
-     * 
-     * @param count
-     *            the number of bytes to skip.
-     * @return the number of bytes actually skipped.
-     * 
-     * @throws IOException
-     *             If the stream is already closed or another IOException
-     *             occurs.
-     */
-    public int skipBytes(int count) throws IOException {
-        if (count > 0) {
-            long currentPos = getFilePointer(), eof = length();
-            int newCount = (int) ((currentPos + count > eof) ? eof - currentPos
-                    : count);
-            seek(currentPos + newCount);
-            return newCount;
-        }
-        return 0;
-    }
-
-    /**
-     * Writes the entire contents of the byte array <code>buffer</code> to
-     * this RandomAccessFile starting at the current file pointer.
-     * 
-     * @param buffer
-     *            the buffer to be written.
-     * 
-     * @throws IOException
-     *             If an error occurs trying to write to this RandomAccessFile.
-     * 
-     * @see #read()
-     * @see #read(byte[])
-     * @see #read(byte[], int, int)
-     */
-    public void write(byte[] buffer) throws IOException {
-        write(buffer, 0, buffer.length);
-    }
-
-    /**
-     * Writes <code>count</code> bytes from the byte array <code>buffer</code>
-     * starting at <code>offset</code> to this RandomAccessFile starting at
-     * the current file pointer..
-     * 
-     * @param buffer
-     *            the bytes to be written
-     * @param offset
-     *            offset in buffer to get bytes
-     * @param count
-     *            number of bytes in buffer to write
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             RandomAccessFile.
-     * @throws IndexOutOfBoundsException
-     *             If offset or count are outside of bounds.
-     * 
-     * @see #read()
-     * @see #read(byte[])
-     * @see #read(byte[], int, int)
-     */
-    public void write(byte[] buffer, int offset, int count) throws IOException {
-    	if (null == buffer) {
-    		throw new NullPointerException();
-    	}
-        if (count < 0 || offset < 0 || count > buffer.length - offset) {
-            throw new IndexOutOfBoundsException();
-        }
-        if (0 == count){
-        	return;
-        }
-        openCheck();
-        synchronized (repositionLock) {
-            fileSystem.write(fd.descriptor, buffer, offset, count);
-        }
-
-        // if we are in "rws" mode, attempt to sync file+metadata
-        if (syncMetadata) {
-            fd.sync();
-        }
-    }
-
-    /**
-     * Writes the specified byte <code>oneByte</code> to this RandomAccessFile
-     * starting at the current file pointer. Only the low order byte of
-     * <code>oneByte</code> is written.
-     * 
-     * @param oneByte
-     *            the byte to be written
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             RandomAccessFile.
-     * 
-     * @see #read()
-     * @see #read(byte[])
-     * @see #read(byte[], int, int)
-     */
-    public void write(int oneByte) throws IOException {
-        openCheck();
-        byte[] bytes = new byte[1];
-        bytes[0] = (byte) (oneByte & 0xff);
-        synchronized (repositionLock) {
-            fileSystem.write(fd.descriptor, bytes, 0, 1);
-        }
-
-        // if we are in "rws" mode, attempt to sync file+metadata
-        if (syncMetadata) {
-            fd.sync();
-        }
-    }
-
-    /**
-     * Writes a boolean to this output stream.
-     * 
-     * @param val
-     *            the boolean value to write to the OutputStream
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see DataInput#readBoolean()
-     */
-    public final void writeBoolean(boolean val) throws IOException {
-        write(val ? 1 : 0);
-    }
-
-    /**
-     * Writes a 8-bit byte to this output stream.
-     * 
-     * @param val
-     *            the byte value to write to the OutputStream
-     * 
-     * @throws java.io.IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see #readByte()
-     * @see #readUnsignedByte()
-     */
-    public final void writeByte(int val) throws IOException {
-        write(val & 0xFF);
-    }
-
-    /**
-     * Writes the low order 8-bit bytes from a String to this output stream.
-     * 
-     * @param str
-     *            the String containing the bytes to write to the OutputStream
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see #read(byte[])
-     * @see #read(byte[],int,int)
-     * @see #readFully(byte[])
-     * @see #readFully(byte[],int,int)
-     */
-    public final void writeBytes(String str) throws IOException {
-        byte bytes[] = new byte[str.length()];
-        for (int index = 0; index < str.length(); index++) {
-            bytes[index] = (byte) (str.charAt(index) & 0xFF);
-        }
-        write(bytes);
-    }
-
-    /**
-     * Writes the specified 16-bit character to the OutputStream. Only the lower
-     * 2 bytes are written with the higher of the 2 bytes written first. This
-     * represents the Unicode value of val.
-     * 
-     * @param val
-     *            the character to be written
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see DataInput#readChar()
-     */
-    public final void writeChar(int val) throws IOException {
-        byte[] buffer = new byte[2];
-        buffer[0] = (byte) (val >> 8);
-        buffer[1] = (byte) val;
-        write(buffer, 0, buffer.length);
-    }
-
-    /**
-     * Writes the specified 16-bit characters contained in str to the
-     * OutputStream. Only the lower 2 bytes of each character are written with
-     * the higher of the 2 bytes written first. This represents the Unicode
-     * value of each character in str.
-     * 
-     * @param str
-     *            the String whose characters are to be written.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see DataInput#readChar()
-     */
-    public final void writeChars(String str) throws IOException {
-        byte newBytes[] = new byte[str.length() * 2];
-        for (int index = 0; index < str.length(); index++) {
-            int newIndex = index == 0 ? index : index * 2;
-            newBytes[newIndex] = (byte) ((str.charAt(index) >> 8) & 0xFF);
-            newBytes[newIndex + 1] = (byte) (str.charAt(index) & 0xFF);
-        }
-        write(newBytes);
-    }
-
-    /**
-     * Writes a 64-bit double to this output stream. The resulting output is the
-     * 8 bytes resulting from calling Double.doubleToLongBits().
-     * 
-     * @param val
-     *            the double to be written.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see DataInput#readDouble()
-     */
-    public final void writeDouble(double val) throws IOException {
-        writeLong(Double.doubleToLongBits(val));
-    }
-
-    /**
-     * Writes a 32-bit float to this output stream. The resulting output is the
-     * 4 bytes resulting from calling Float.floatToIntBits().
-     * 
-     * @param val
-     *            the float to be written.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see DataInput#readFloat()
-     */
-    public final void writeFloat(float val) throws IOException {
-        writeInt(Float.floatToIntBits(val));
-    }
-
-    /**
-     * Writes a 32-bit int to this output stream. The resulting output is the 4
-     * bytes, highest order first, of val.
-     * 
-     * @param val
-     *            the int to be written.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see DataInput#readInt()
-     */
-    public final void writeInt(int val) throws IOException {
-        byte[] buffer = new byte[4];
-        buffer[0] = (byte) (val >> 24);
-        buffer[1] = (byte) (val >> 16);
-        buffer[2] = (byte) (val >> 8);
-        buffer[3] = (byte) val;
-        write(buffer, 0, buffer.length);
-    }
-
-    /**
-     * Writes a 64-bit long to this output stream. The resulting output is the 8
-     * bytes, highest order first, of val.
-     * 
-     * @param val
-     *            the long to be written.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see DataInput#readLong()
-     */
-    public final void writeLong(long val) throws IOException {
-        byte[] buffer = new byte[8];
-        int t = (int) (val >> 32);
-        buffer[0] = (byte) (t >> 24);
-        buffer[1] = (byte) (t >> 16);
-        buffer[2] = (byte) (t >> 8);
-        buffer[3] = (byte) t;
-        buffer[4] = (byte) (val >> 24);
-        buffer[5] = (byte) (val >> 16);
-        buffer[6] = (byte) (val >> 8);
-        buffer[7] = (byte) val;
-        write(buffer, 0, buffer.length);
-    }
-
-    /**
-     * Writes the specified 16-bit short to the OutputStream. Only the lower 2
-     * bytes are written with the higher of the 2 bytes written first.
-     * 
-     * @param val
-     *            the short to be written
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see DataInput#readShort()
-     * @see DataInput#readUnsignedShort()
-     */
-    public final void writeShort(int val) throws IOException {
-        writeChar(val);
-    }
-
-    /**
-     * Writes the specified String out in UTF format.
-     * 
-     * @param str
-     *            the String to be written in UTF format.
-     * 
-     * @throws IOException
-     *             If an error occurs attempting to write to this
-     *             DataOutputStream.
-     * 
-     * @see DataInput#readUTF()
-     */
-    public final void writeUTF(String str) throws IOException {
-        int utfCount = 0, length = str.length();
-        for (int i = 0; i < length; i++) {
-            int charValue = str.charAt(i);
-            if (charValue > 0 && charValue <= 127) {
-                utfCount++;
-            } else if (charValue <= 2047) {
-                utfCount += 2;
-            } else {
-                utfCount += 3;
-            }
-        }
-        if (utfCount <= 65535) {
-            byte utfBytes[] = new byte[utfCount + 2];
-            int utfIndex = 2;
-            for (int i = 0; i < length; i++) {
-                int charValue = str.charAt(i);
-                if (charValue > 0 && charValue <= 127) {
-                    utfBytes[utfIndex++] = (byte) charValue;
-                } else if (charValue <= 2047) {
-                    utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                } else {
-                    utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                }
-            }
-            utfBytes[0] = (byte) (utfCount >> 8);
-            utfBytes[1] = (byte) utfCount;
-            write(utfBytes);
-        } else {
-            throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
-        }
-    }
-}
+/* Copyright 1998, 2006 The Apache Software Foundation or its licensors, as applicable
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package java.io;
+
+import java.nio.channels.FileChannel;
+
+import org.apache.harmony.luni.platform.IFileSystem;
+import org.apache.harmony.luni.platform.Platform;
+import org.apache.harmony.luni.util.Msg;
+import org.apache.harmony.luni.util.Util;
+
+import org.apache.harmony.nio.FileChannelFactory;
+
+/**
+ * RandomAccessFile is a class which allows positioning of the next read
+ * anywhere in the file. This is useful for reading specific locations of files
+ * or following links within a file. Most input classes only support forward
+ * skipping.
+ */
+public class RandomAccessFile implements DataInput, DataOutput, Closeable {
+    /**
+     * The FileDescriptor representing this RandomAccessFile.
+     */
+    private FileDescriptor fd;
+
+    private boolean syncMetadata = false;
+
+    // The unique file channel associated with this FileInputStream (lazily
+    // initialized).
+    private FileChannel channel;
+
+    private IFileSystem fileSystem = Platform.getFileSystem();
+
+    private boolean isReadOnly;
+
+    private Object repositionLock = new Object();
+
+    /**
+     * Constructs a new RandomAccessFile on the File <code>file</code> and
+     * opens it according to the access String in <code>mode</code>. The
+     * access mode may be one of <code>"r"</code> for read access only, or
+     * <code>"rw"</code> for read/write access.
+     * 
+     * @param file
+     *            the File to open.
+     * @param mode
+     *            "r" for read only, or "rw" for read/write.
+     * 
+     * @throws FileNotFoundException
+     *             If the <code>mode</code> is incorrect or the File cannot be
+     *             opened in the requested <code>mode</code>.
+     * 
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
+     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
+     */
+    public RandomAccessFile(File file, String mode)
+            throws FileNotFoundException {
+        super();
+
+        int options = 0;
+
+        if (mode.equals("r")) { //$NON-NLS-1$
+            isReadOnly = true;
+            options = IFileSystem.O_RDONLY;
+        } else if (mode.equals("rw") || mode.equals("rws") || mode.equals("rwd")) { //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+            isReadOnly = false;
+            options = IFileSystem.O_RDWR;
+
+            if (mode.equals("rws")) { //$NON-NLS-1$
+                // Sync file and metadata with every write
+                syncMetadata = true;
+            } else if (mode.equals("rwd")) { //$NON-NLS-1$
+                // Sync file, but not necessarily metadata
+                options = IFileSystem.O_RDWRSYNC;
+            }
+
+        } else {
+            throw new IllegalArgumentException(Msg.getString("K0081")); //$NON-NLS-1$
+        }
+
+        SecurityManager security = System.getSecurityManager();
+        if (security != null) {
+            security.checkRead(file.getPath());
+            if (!isReadOnly) {
+                security.checkWrite(file.getPath());
+            }
+        }
+
+        fd = new FileDescriptor();
+        fd.descriptor = fileSystem.open(file.properPath(true), options);
+        channel = FileChannelFactory.getFileChannel(this, fd.descriptor,
+                options);
+
+        // if we are in "rws" mode, attempt to sync file+metadata
+        if (syncMetadata) {
+            try {
+                fd.sync();
+            } catch (IOException e) {
+            }
+        }
+    }
+
+    /**
+     * Constructs a new RandomAccessFile on the file named <code>fileName</code>
+     * and opens it according to the access String in <code>mode</code>. The
+     * file may be absolute or relative to the System property
+     * <code>"user.dir"</code>. The access mode may be one of
+     * <code>"r"</code> for read access only, or <code>"rw"</code> for
+     * read/write access.
+     * 
+     * 
+     * @param fileName
+     *            the filename of the file to open.
+     * @param mode
+     *            "r" for read only, or "rw" for read/write.
+     * 
+     * @throws FileNotFoundException
+     *             If the <code>mode</code> is incorrect or the file cannot be
+     *             opened in the requested <code>mode</code>.
+     * 
+     * @see java.lang.SecurityManager#checkRead(FileDescriptor)
+     * @see java.lang.SecurityManager#checkWrite(FileDescriptor)
+     */
+    public RandomAccessFile(String fileName, String mode)
+            throws FileNotFoundException {
+        this(new File(fileName), mode);
+    }
+
+    /**
+     * Close this RandomAccessFile.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to close this RandomAccessFile.
+     */
+    public void close() throws IOException {
+        synchronized (channel) {
+            synchronized (this) {
+                if (channel.isOpen() && fd.descriptor >= 0) {
+                    channel.close();
+                }
+                fd.descriptor = -1;
+            }
+        }
+    }
+
+    /**
+     * Answers the FileChannel equivalent to this stream.
+     * <p>
+     * The file channel is write-only and has an initial position within the
+     * file that is the same as the current position of this FileOutputStream
+     * within the file. All changes made to the underlying file descriptor state
+     * via the channel are visible by the output stream and vice versa.
+     * </p>
+     * 
+     * @return the file channel representation for this FileOutputStream.
+     */
+    public final synchronized FileChannel getChannel() {
+        return channel;
+    }
+
+    /**
+     * Answers the FileDescriptor representing the operating system resource for
+     * this RandomAccessFile.
+     * 
+     * @return the FileDescriptor for this RandomAccessFile.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to get the FileDescriptor of
+     *             this RandomAccessFile.
+     */
+    public final FileDescriptor getFD() throws IOException {
+        return fd;
+    }
+
+    /**
+     * Answers the current position within this RandomAccessFile. All reads and
+     * writes take place at the current file pointer position.
+     * 
+     * @return the current file pointer position.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to get the file pointer
+     *             position of this RandomAccessFile.
+     */
+    public long getFilePointer() throws IOException {
+        openCheck();
+        return fileSystem.seek(fd.descriptor, 0L, IFileSystem.SEEK_CUR);
+    }
+
+    private synchronized void openCheck() throws IOException {
+        if (fd.descriptor < 0) {
+            throw new IOException();
+        }
+    }
+
+    /**
+     * Answers the current length of this RandomAccessFile in bytes.
+     * 
+     * @return the current file length in bytes.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to get the file length of this
+     *             RandomAccessFile.
+     */
+    public long length() throws IOException {
+        openCheck();
+        synchronized (repositionLock) {
+            long currentPosition = fileSystem.seek(fd.descriptor, 0L,
+                    IFileSystem.SEEK_CUR);
+            long endOfFilePosition = fileSystem.seek(fd.descriptor, 0L,
+                    IFileSystem.SEEK_END);
+            fileSystem.seek(fd.descriptor, currentPosition,
+                    IFileSystem.SEEK_SET);
+            return endOfFilePosition;
+        }
+    }
+
+    /**
+     * Reads a single byte from this RandomAccessFile and returns the result as
+     * an int. The low-order byte is returned or -1 of the end of file was
+     * encountered.
+     * 
+     * @return the byte read or -1 if end of file.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to read from this
+     *             RandomAccessFile.
+     * 
+     * @see #write(byte[])
+     * @see #write(byte[], int, int)
+     * @see #write(int)
+     */
+    public int read() throws IOException {
+        openCheck();
+        byte[] bytes = new byte[1];
+        synchronized (repositionLock) {
+            long readed = fileSystem.read(fd.descriptor, bytes, 0, 1);
+            return readed == -1 ? -1 : bytes[0] & 0xff;
+        }
+    }
+
+    /**
+     * Reads bytes from this RandomAccessFile into the byte array
+     * <code>buffer</code>. The number of bytes actually read is returned.
+     * 
+     * @param buffer
+     *            the buffer to read bytes into
+     * @return the number of bytes actually read or -1 if end of file.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to read from this
+     *             RandomAccessFile.
+     * 
+     * @see #write(byte[])
+     * @see #write(byte[], int, int)
+     * @see #write(int)
+     */
+    public int read(byte[] buffer) throws IOException {
+        return read(buffer, 0, buffer.length);
+    }
+
+    /**
+     * Reads at most <code>count</code> bytes from this RandomAccessFile and
+     * stores them in byte array <code>buffer</code> starting at
+     * <code>offset</code>. Answer the number of bytes actually read or -1 if
+     * no bytes were read and end of file was encountered.
+     * 
+     * @param buffer
+     *            the byte array in which to store the read bytes.
+     * @param offset
+     *            the offset in <code>buffer</code> to store the read bytes.
+     * @param count
+     *            the maximum number of bytes to store in <code>buffer</code>.
+     * @return the number of bytes actually read or -1 if end of file.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to read from this
+     *             RandomAccessFile.
+     * 
+     * @see #write(byte[])
+     * @see #write(byte[], int, int)
+     * @see #write(int)
+     */
+    public int read(byte[] buffer, int offset, int count) throws IOException {
+        // have to have four comparisions to not miss integer overflow cases
+        if (count > buffer.length - offset || count < 0 || offset < 0) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (0 == count) {
+            return 0;
+        }
+        openCheck();
+        synchronized (repositionLock) {
+            return (int) fileSystem.read(fd.descriptor, buffer, offset, count);
+        }
+    }
+
+    /**
+     * Reads a boolean from this stream.
+     * 
+     * @return boolean the next boolean value from the source stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeBoolean(boolean)
+     */
+    public final boolean readBoolean() throws IOException {
+        int temp = this.read();
+        if (temp >= 0) {
+            return temp != 0;
+        }
+        throw new EOFException();
+    }
+
+    /**
+     * Reads an 8-bit byte value from this stream.
+     * 
+     * @return byte the next byte value from the source stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeByte(int)
+     */
+    public final byte readByte() throws IOException {
+        int temp = this.read();
+        if (temp >= 0) {
+            return (byte) temp;
+        }
+        throw new EOFException();
+    }
+
+    /**
+     * Reads a 16-bit character value from this stream.
+     * 
+     * @return char the next <code>char</code> value from the source stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeChar(int)
+     */
+    public final char readChar() throws IOException {
+        byte[] buffer = new byte[2];
+        if (read(buffer, 0, buffer.length) == buffer.length) {
+            return (char) (((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff));
+        }
+        throw new EOFException();
+    }
+
+    /**
+     * Reads a 64-bit <code>double</code> value from this stream.
+     * 
+     * @return double the next <code>double</code> value from the source
+     *         stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeDouble(double)
+     */
+    public final double readDouble() throws IOException {
+        return Double.longBitsToDouble(readLong());
+    }
+
+    /**
+     * Reads a 32-bit <code>float</code> value from this stream.
+     * 
+     * @return float the next <code>float</code> value from the source stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeFloat(float)
+     */
+    public final float readFloat() throws IOException {
+        return Float.intBitsToFloat(readInt());
+    }
+
+    /**
+     * Reads bytes from this stream into the byte array <code>buffer</code>.
+     * This method will block until <code>buffer.length</code> number of bytes
+     * have been read.
+     * 
+     * @param buffer
+     *            the buffer to read bytes into
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#write(byte[])
+     * @see DataOutput#write(byte[], int, int)
+     */
+    public final void readFully(byte[] buffer) throws IOException {
+        readFully(buffer, 0, buffer.length);
+    }
+
+    /**
+     * Read bytes from this stream and stores them in byte array
+     * <code>buffer</code> starting at offset <code>offset</code>. This
+     * method blocks until <code>count</code> number of bytes have been read.
+     * 
+     * @param buffer
+     *            the byte array in which to store the read bytes.
+     * @param offset
+     *            the offset in <code>buffer</code> to store the read bytes.
+     * @param count
+     *            the maximum number of bytes to store in <code>buffer</code>.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#write(byte[])
+     * @see DataOutput#write(byte[], int, int)
+     */
+    public final void readFully(byte[] buffer, int offset, int count)
+            throws IOException {
+        if (buffer != null) {
+            // avoid int overflow
+            if (0 <= offset && offset <= buffer.length && 0 <= count
+                    && count <= buffer.length - offset) {
+                while (count > 0) {
+                    int result = read(buffer, offset, count);
+                    if (result >= 0) {
+                        offset += result;
+                        count -= result;
+                    } else {
+                        throw new EOFException();
+                    }
+                }
+            } else {
+                throw new IndexOutOfBoundsException();
+            }
+        } else {
+            throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$
+        }
+    }
+
+    /**
+     * Reads a 32-bit integer value from this stream.
+     * 
+     * @return int the next <code>int</code> value from the source stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeInt(int)
+     */
+    public final int readInt() throws IOException {
+        byte[] buffer = new byte[4];
+        if (read(buffer, 0, buffer.length) == buffer.length) {
+            return ((buffer[0] & 0xff) << 24) + ((buffer[1] & 0xff) << 16)
+                    + ((buffer[2] & 0xff) << 8) + (buffer[3] & 0xff);
+        }
+        throw new EOFException();
+    }
+
+    /**
+     * Answers a <code>String</code> representing the next line of text
+     * available in this BufferedReader. A line is represented by 0 or more
+     * characters followed by <code>'\n'</code>, <code>'\r'</code>,
+     * <code>"\n\r"</code> or end of stream. The <code>String</code> does
+     * not include the newline sequence.
+     * 
+     * @return String the contents of the line or null if no characters were
+     *         read before end of stream.
+     * 
+     * @throws IOException
+     *             If the BufferedReader is already closed or some other IO
+     *             error occurs.
+     */
+    public final String readLine() throws IOException {
+        StringBuilder line = new StringBuilder(80); // Typical line length
+        boolean foundTerminator = false;
+        long unreadPosition = 0;
+        while (true) {
+            int nextByte = read();
+            switch (nextByte) {
+                case -1:
+                    return line.length() != 0 ? line.toString() : null;
+                case (byte) '\r':
+                    if (foundTerminator) {
+                        seek(unreadPosition);
+                        return line.toString();
+                    }
+                    foundTerminator = true;
+                    /* Have to be able to peek ahead one byte */
+                    unreadPosition = getFilePointer();
+                    break;
+                case (byte) '\n':
+                    return line.toString();
+                default:
+                    if (foundTerminator) {
+                        seek(unreadPosition);
+                        return line.toString();
+                    }
+                    line.append((char) nextByte);
+            }
+        }
+    }
+
+    /**
+     * Reads a 64-bit <code>long</code> value from this stream.
+     * 
+     * @return long the next <code>long</code> value from the source stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeLong(long)
+     */
+    public final long readLong() throws IOException {
+        byte[] buffer = new byte[8];
+        if (read(buffer, 0, buffer.length) == buffer.length) {
+            return ((long) (((buffer[0] & 0xff) << 24)
+                    + ((buffer[1] & 0xff) << 16) + ((buffer[2] & 0xff) << 8) + (buffer[3] & 0xff)) << 32)
+                    + ((long) (buffer[4] & 0xff) << 24)
+                    + ((buffer[5] & 0xff) << 16)
+                    + ((buffer[6] & 0xff) << 8)
+                    + (buffer[7] & 0xff);
+        }
+        throw new EOFException();
+    }
+
+    /**
+     * Reads a 16-bit <code>short</code> value from this stream.
+     * 
+     * @return short the next <code>short</code> value from the source stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeShort(int)
+     */
+    public final short readShort() throws IOException {
+        byte[] buffer = new byte[2];
+        if (read(buffer, 0, buffer.length) == buffer.length) {
+            return (short) (((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff));
+        }
+        throw new EOFException();
+    }
+
+    /**
+     * Reads an unsigned 8-bit <code>byte</code> value from this stream and
+     * returns it as an int.
+     * 
+     * @return int the next unsigned byte value from the source stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeByte(int)
+     */
+    public final int readUnsignedByte() throws IOException {
+        int temp = this.read();
+        if (temp >= 0) {
+            return temp;
+        }
+        throw new EOFException();
+    }
+
+    /**
+     * Reads a 16-bit unsigned <code>short</code> value from this stream and
+     * returns it as an int.
+     * 
+     * @return int the next unsigned <code>short</code> value from the source
+     *         stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeShort(int)
+     */
+    public final int readUnsignedShort() throws IOException {
+        byte[] buffer = new byte[2];
+        if (read(buffer, 0, buffer.length) == buffer.length) {
+            return ((buffer[0] & 0xff) << 8) + (buffer[1] & 0xff);
+        }
+        throw new EOFException();
+    }
+
+    /**
+     * Reads a UTF format String from this Stream.
+     * 
+     * @return String the next UTF String from the source stream.
+     * 
+     * @throws IOException
+     *             If a problem occurs reading from this DataInputStream.
+     * 
+     * @see DataOutput#writeUTF(java.lang.String)
+     */
+    public final String readUTF() throws IOException {
+        int utfSize = readUnsignedShort();
+        if (utfSize == 0) {
+            return new String();
+        }
+        byte[] buf = new byte[utfSize];
+        if (read(buf, 0, buf.length) == buf.length) {
+            return Util.convertFromUTF8(buf, 0, utfSize);
+        }
+        throw new EOFException();
+    }
+
+    /**
+     * Seeks to the position <code>pos</code> in this RandomAccessFile. All
+     * read/write/skip methods sent will be relative to <code>pos</code>.
+     * 
+     * @param pos
+     *            the desired file pointer position
+     * 
+     * @throws IOException
+     *             If the stream is already closed or another IOException
+     *             occurs.
+     */
+    public void seek(long pos) throws IOException {
+        if (pos < 0) {
+            // seek position is negative
+            throw new IOException(Msg.getString("K0347")); //$NON-NLS-1$
+        }
+        openCheck();
+        synchronized (repositionLock) {
+            fileSystem.seek(fd.descriptor, pos, IFileSystem.SEEK_SET);
+        }
+    }
+
+    /**
+     * Set the length of this file to be <code>newLength</code>. If the
+     * current file is smaller, it will be expanded and the filePosition will be
+     * set to the new file length. If the <code>newLength</code> is smaller
+     * then the file will be truncated.
+     * 
+     * @param newLength
+     *            the desired file length
+     * 
+     * @throws IOException
+     *             If the stream is already closed or another IOException
+     *             occurs.
+     */
+    public void setLength(long newLength) throws IOException {
+        openCheck();
+        if (newLength < 0) {
+            throw new IllegalArgumentException();
+        }
+        synchronized (repositionLock) {
+            long position = fileSystem.seek(fd.descriptor, 0,
+                    IFileSystem.SEEK_CUR);
+            fileSystem.truncate(fd.descriptor, newLength);
+            seek(position > newLength ? newLength : position);
+        }
+
+        // if we are in "rws" mode, attempt to sync file+metadata
+        if (syncMetadata) {
+            fd.sync();
+        }
+    }
+
+    /**
+     * Skips <code>count</code> number of bytes in this stream. Subsequent
+     * <code>read()</code>'s will not return these bytes unless
+     * <code>reset()</code> is used.
+     * 
+     * @param count
+     *            the number of bytes to skip.
+     * @return the number of bytes actually skipped.
+     * 
+     * @throws IOException
+     *             If the stream is already closed or another IOException
+     *             occurs.
+     */
+    public int skipBytes(int count) throws IOException {
+        if (count > 0) {
+            long currentPos = getFilePointer(), eof = length();
+            int newCount = (int) ((currentPos + count > eof) ? eof - currentPos
+                    : count);
+            seek(currentPos + newCount);
+            return newCount;
+        }
+        return 0;
+    }
+
+    /**
+     * Writes the entire contents of the byte array <code>buffer</code> to
+     * this RandomAccessFile starting at the current file pointer.
+     * 
+     * @param buffer
+     *            the buffer to be written.
+     * 
+     * @throws IOException
+     *             If an error occurs trying to write to this RandomAccessFile.
+     * 
+     * @see #read()
+     * @see #read(byte[])
+     * @see #read(byte[], int, int)
+     */
+    public void write(byte[] buffer) throws IOException {
+        write(buffer, 0, buffer.length);
+    }
+
+    /**
+     * Writes <code>count</code> bytes from the byte array <code>buffer</code>
+     * starting at <code>offset</code> to this RandomAccessFile starting at
+     * the current file pointer..
+     * 
+     * @param buffer
+     *            the bytes to be written
+     * @param offset
+     *            offset in buffer to get bytes
+     * @param count
+     *            number of bytes in buffer to write
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             RandomAccessFile.
+     * @throws IndexOutOfBoundsException
+     *             If offset or count are outside of bounds.
+     * 
+     * @see #read()
+     * @see #read(byte[])
+     * @see #read(byte[], int, int)
+     */
+    public void write(byte[] buffer, int offset, int count) throws IOException {
+    	if (null == buffer) {
+    		throw new NullPointerException();
+    	}
+        if (count < 0 || offset < 0 || count > buffer.length - offset) {
+            throw new IndexOutOfBoundsException();
+        }
+        if (0 == count){
+        	return;
+        }
+        openCheck();
+        synchronized (repositionLock) {
+            fileSystem.write(fd.descriptor, buffer, offset, count);
+        }
+
+        // if we are in "rws" mode, attempt to sync file+metadata
+        if (syncMetadata) {
+            fd.sync();
+        }
+    }
+
+    /**
+     * Writes the specified byte <code>oneByte</code> to this RandomAccessFile
+     * starting at the current file pointer. Only the low order byte of
+     * <code>oneByte</code> is written.
+     * 
+     * @param oneByte
+     *            the byte to be written
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             RandomAccessFile.
+     * 
+     * @see #read()
+     * @see #read(byte[])
+     * @see #read(byte[], int, int)
+     */
+    public void write(int oneByte) throws IOException {
+        openCheck();
+        byte[] bytes = new byte[1];
+        bytes[0] = (byte) (oneByte & 0xff);
+        synchronized (repositionLock) {
+            fileSystem.write(fd.descriptor, bytes, 0, 1);
+        }
+
+        // if we are in "rws" mode, attempt to sync file+metadata
+        if (syncMetadata) {
+            fd.sync();
+        }
+    }
+
+    /**
+     * Writes a boolean to this output stream.
+     * 
+     * @param val
+     *            the boolean value to write to the OutputStream
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see DataInput#readBoolean()
+     */
+    public final void writeBoolean(boolean val) throws IOException {
+        write(val ? 1 : 0);
+    }
+
+    /**
+     * Writes a 8-bit byte to this output stream.
+     * 
+     * @param val
+     *            the byte value to write to the OutputStream
+     * 
+     * @throws java.io.IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see #readByte()
+     * @see #readUnsignedByte()
+     */
+    public final void writeByte(int val) throws IOException {
+        write(val & 0xFF);
+    }
+
+    /**
+     * Writes the low order 8-bit bytes from a String to this output stream.
+     * 
+     * @param str
+     *            the String containing the bytes to write to the OutputStream
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see #read(byte[])
+     * @see #read(byte[],int,int)
+     * @see #readFully(byte[])
+     * @see #readFully(byte[],int,int)
+     */
+    public final void writeBytes(String str) throws IOException {
+        byte bytes[] = new byte[str.length()];
+        for (int index = 0; index < str.length(); index++) {
+            bytes[index] = (byte) (str.charAt(index) & 0xFF);
+        }
+        write(bytes);
+    }
+
+    /**
+     * Writes the specified 16-bit character to the OutputStream. Only the lower
+     * 2 bytes are written with the higher of the 2 bytes written first. This
+     * represents the Unicode value of val.
+     * 
+     * @param val
+     *            the character to be written
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see DataInput#readChar()
+     */
+    public final void writeChar(int val) throws IOException {
+        byte[] buffer = new byte[2];
+        buffer[0] = (byte) (val >> 8);
+        buffer[1] = (byte) val;
+        write(buffer, 0, buffer.length);
+    }
+
+    /**
+     * Writes the specified 16-bit characters contained in str to the
+     * OutputStream. Only the lower 2 bytes of each character are written with
+     * the higher of the 2 bytes written first. This represents the Unicode
+     * value of each character in str.
+     * 
+     * @param str
+     *            the String whose characters are to be written.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see DataInput#readChar()
+     */
+    public final void writeChars(String str) throws IOException {
+        byte newBytes[] = new byte[str.length() * 2];
+        for (int index = 0; index < str.length(); index++) {
+            int newIndex = index == 0 ? index : index * 2;
+            newBytes[newIndex] = (byte) ((str.charAt(index) >> 8) & 0xFF);
+            newBytes[newIndex + 1] = (byte) (str.charAt(index) & 0xFF);
+        }
+        write(newBytes);
+    }
+
+    /**
+     * Writes a 64-bit double to this output stream. The resulting output is the
+     * 8 bytes resulting from calling Double.doubleToLongBits().
+     * 
+     * @param val
+     *            the double to be written.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see DataInput#readDouble()
+     */
+    public final void writeDouble(double val) throws IOException {
+        writeLong(Double.doubleToLongBits(val));
+    }
+
+    /**
+     * Writes a 32-bit float to this output stream. The resulting output is the
+     * 4 bytes resulting from calling Float.floatToIntBits().
+     * 
+     * @param val
+     *            the float to be written.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see DataInput#readFloat()
+     */
+    public final void writeFloat(float val) throws IOException {
+        writeInt(Float.floatToIntBits(val));
+    }
+
+    /**
+     * Writes a 32-bit int to this output stream. The resulting output is the 4
+     * bytes, highest order first, of val.
+     * 
+     * @param val
+     *            the int to be written.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see DataInput#readInt()
+     */
+    public final void writeInt(int val) throws IOException {
+        byte[] buffer = new byte[4];
+        buffer[0] = (byte) (val >> 24);
+        buffer[1] = (byte) (val >> 16);
+        buffer[2] = (byte) (val >> 8);
+        buffer[3] = (byte) val;
+        write(buffer, 0, buffer.length);
+    }
+
+    /**
+     * Writes a 64-bit long to this output stream. The resulting output is the 8
+     * bytes, highest order first, of val.
+     * 
+     * @param val
+     *            the long to be written.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see DataInput#readLong()
+     */
+    public final void writeLong(long val) throws IOException {
+        byte[] buffer = new byte[8];
+        int t = (int) (val >> 32);
+        buffer[0] = (byte) (t >> 24);
+        buffer[1] = (byte) (t >> 16);
+        buffer[2] = (byte) (t >> 8);
+        buffer[3] = (byte) t;
+        buffer[4] = (byte) (val >> 24);
+        buffer[5] = (byte) (val >> 16);
+        buffer[6] = (byte) (val >> 8);
+        buffer[7] = (byte) val;
+        write(buffer, 0, buffer.length);
+    }
+
+    /**
+     * Writes the specified 16-bit short to the OutputStream. Only the lower 2
+     * bytes are written with the higher of the 2 bytes written first.
+     * 
+     * @param val
+     *            the short to be written
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see DataInput#readShort()
+     * @see DataInput#readUnsignedShort()
+     */
+    public final void writeShort(int val) throws IOException {
+        writeChar(val);
+    }
+
+    /**
+     * Writes the specified String out in UTF format.
+     * 
+     * @param str
+     *            the String to be written in UTF format.
+     * 
+     * @throws IOException
+     *             If an error occurs attempting to write to this
+     *             DataOutputStream.
+     * 
+     * @see DataInput#readUTF()
+     */
+    public final void writeUTF(String str) throws IOException {
+        int utfCount = 0, length = str.length();
+        for (int i = 0; i < length; i++) {
+            int charValue = str.charAt(i);
+            if (charValue > 0 && charValue <= 127) {
+                utfCount++;
+            } else if (charValue <= 2047) {
+                utfCount += 2;
+            } else {
+                utfCount += 3;
+            }
+        }
+        if (utfCount <= 65535) {
+            byte utfBytes[] = new byte[utfCount + 2];
+            int utfIndex = 2;
+            for (int i = 0; i < length; i++) {
+                int charValue = str.charAt(i);
+                if (charValue > 0 && charValue <= 127) {
+                    utfBytes[utfIndex++] = (byte) charValue;
+                } else if (charValue <= 2047) {
+                    utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
+                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
+                } else {
+                    utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
+                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
+                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
+                }
+            }
+            utfBytes[0] = (byte) (utfCount >> 8);
+            utfBytes[1] = (byte) utfCount;
+            write(utfBytes);
+        } else {
+            throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
+        }
+    }
+}

Propchange: incubator/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/RandomAccessFile.java
------------------------------------------------------------------------------
    svn:eol-style = native