jaroslav@557: /* jaroslav@557: * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. jaroslav@557: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. jaroslav@557: * jaroslav@557: * This code is free software; you can redistribute it and/or modify it jaroslav@557: * under the terms of the GNU General Public License version 2 only, as jaroslav@557: * published by the Free Software Foundation. Oracle designates this jaroslav@557: * particular file as subject to the "Classpath" exception as provided jaroslav@557: * by Oracle in the LICENSE file that accompanied this code. jaroslav@557: * jaroslav@557: * This code is distributed in the hope that it will be useful, but WITHOUT jaroslav@557: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or jaroslav@557: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License jaroslav@557: * version 2 for more details (a copy is included in the LICENSE file that jaroslav@557: * accompanied this code). jaroslav@557: * jaroslav@557: * You should have received a copy of the GNU General Public License version jaroslav@557: * 2 along with this work; if not, write to the Free Software Foundation, jaroslav@557: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. jaroslav@557: * jaroslav@557: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA jaroslav@557: * or visit www.oracle.com if you need additional information or have any jaroslav@557: * questions. jaroslav@557: */ jaroslav@557: jaroslav@557: package java.io; jaroslav@557: jaroslav@557: jaroslav@557: /** jaroslav@557: * Abstract class for reading character streams. The only methods that a jaroslav@557: * subclass must implement are read(char[], int, int) and close(). Most jaroslav@557: * subclasses, however, will override some of the methods defined here in order jaroslav@557: * to provide higher efficiency, additional functionality, or both. jaroslav@557: * jaroslav@557: * jaroslav@557: * @see BufferedReader jaroslav@557: * @see LineNumberReader jaroslav@557: * @see CharArrayReader jaroslav@557: * @see InputStreamReader jaroslav@557: * @see FileReader jaroslav@557: * @see FilterReader jaroslav@557: * @see PushbackReader jaroslav@557: * @see PipedReader jaroslav@557: * @see StringReader jaroslav@557: * @see Writer jaroslav@557: * jaroslav@557: * @author Mark Reinhold jaroslav@557: * @since JDK1.1 jaroslav@557: */ jaroslav@557: jaroslav@557: public abstract class Reader implements Readable, Closeable { jaroslav@557: jaroslav@557: /** jaroslav@557: * The object used to synchronize operations on this stream. For jaroslav@557: * efficiency, a character-stream object may use an object other than jaroslav@557: * itself to protect critical sections. A subclass should therefore use jaroslav@557: * the object in this field rather than this or a synchronized jaroslav@557: * method. jaroslav@557: */ jaroslav@557: protected Object lock; jaroslav@557: jaroslav@557: /** jaroslav@557: * Creates a new character-stream reader whose critical sections will jaroslav@557: * synchronize on the reader itself. jaroslav@557: */ jaroslav@557: protected Reader() { jaroslav@557: this.lock = this; jaroslav@557: } jaroslav@557: jaroslav@557: /** jaroslav@557: * Creates a new character-stream reader whose critical sections will jaroslav@557: * synchronize on the given object. jaroslav@557: * jaroslav@557: * @param lock The Object to synchronize on. jaroslav@557: */ jaroslav@557: protected Reader(Object lock) { jaroslav@557: if (lock == null) { jaroslav@557: throw new NullPointerException(); jaroslav@557: } jaroslav@557: this.lock = lock; jaroslav@557: } jaroslav@557: jaroslav@557: /** jaroslav@557: * Attempts to read characters into the specified character buffer. jaroslav@557: * The buffer is used as a repository of characters as-is: the only jaroslav@557: * changes made are the results of a put operation. No flipping or jaroslav@557: * rewinding of the buffer is performed. jaroslav@557: * jaroslav@557: * @param target the buffer to read characters into jaroslav@557: * @return The number of characters added to the buffer, or jaroslav@557: * -1 if this source of characters is at its end jaroslav@557: * @throws IOException if an I/O error occurs jaroslav@557: * @throws NullPointerException if target is null jaroslav@557: * @throws ReadOnlyBufferException if target is a read only buffer jaroslav@557: * @since 1.5 jaroslav@557: */ jaroslav@560: // public int read(java.nio.CharBuffer target) throws IOException { jaroslav@560: // int len = target.remaining(); jaroslav@560: // char[] cbuf = new char[len]; jaroslav@560: // int n = read(cbuf, 0, len); jaroslav@560: // if (n > 0) jaroslav@560: // target.put(cbuf, 0, n); jaroslav@560: // return n; jaroslav@560: // } jaroslav@557: jaroslav@557: /** jaroslav@557: * Reads a single character. This method will block until a character is jaroslav@557: * available, an I/O error occurs, or the end of the stream is reached. jaroslav@557: * jaroslav@557: *

Subclasses that intend to support efficient single-character input jaroslav@557: * should override this method. jaroslav@557: * jaroslav@557: * @return The character read, as an integer in the range 0 to 65535 jaroslav@557: * (0x00-0xffff), or -1 if the end of the stream has jaroslav@557: * been reached jaroslav@557: * jaroslav@557: * @exception IOException If an I/O error occurs jaroslav@557: */ jaroslav@557: public int read() throws IOException { jaroslav@557: char cb[] = new char[1]; jaroslav@557: if (read(cb, 0, 1) == -1) jaroslav@557: return -1; jaroslav@557: else jaroslav@557: return cb[0]; jaroslav@557: } jaroslav@557: jaroslav@557: /** jaroslav@557: * Reads characters into an array. This method will block until some input jaroslav@557: * is available, an I/O error occurs, or the end of the stream is reached. jaroslav@557: * jaroslav@557: * @param cbuf Destination buffer jaroslav@557: * jaroslav@557: * @return The number of characters read, or -1 jaroslav@557: * if the end of the stream jaroslav@557: * has been reached jaroslav@557: * jaroslav@557: * @exception IOException If an I/O error occurs jaroslav@557: */ jaroslav@557: public int read(char cbuf[]) throws IOException { jaroslav@557: return read(cbuf, 0, cbuf.length); jaroslav@557: } jaroslav@557: jaroslav@557: /** jaroslav@557: * Reads characters into a portion of an array. This method will block jaroslav@557: * until some input is available, an I/O error occurs, or the end of the jaroslav@557: * stream is reached. jaroslav@557: * jaroslav@557: * @param cbuf Destination buffer jaroslav@557: * @param off Offset at which to start storing characters jaroslav@557: * @param len Maximum number of characters to read jaroslav@557: * jaroslav@557: * @return The number of characters read, or -1 if the end of the jaroslav@557: * stream has been reached jaroslav@557: * jaroslav@557: * @exception IOException If an I/O error occurs jaroslav@557: */ jaroslav@557: abstract public int read(char cbuf[], int off, int len) throws IOException; jaroslav@557: jaroslav@557: /** Maximum skip-buffer size */ jaroslav@557: private static final int maxSkipBufferSize = 8192; jaroslav@557: jaroslav@557: /** Skip buffer, null until allocated */ jaroslav@557: private char skipBuffer[] = null; jaroslav@557: jaroslav@557: /** jaroslav@557: * Skips characters. This method will block until some characters are jaroslav@557: * available, an I/O error occurs, or the end of the stream is reached. jaroslav@557: * jaroslav@557: * @param n The number of characters to skip jaroslav@557: * jaroslav@557: * @return The number of characters actually skipped jaroslav@557: * jaroslav@557: * @exception IllegalArgumentException If n is negative. jaroslav@557: * @exception IOException If an I/O error occurs jaroslav@557: */ jaroslav@557: public long skip(long n) throws IOException { jaroslav@557: if (n < 0L) jaroslav@557: throw new IllegalArgumentException("skip value is negative"); jaroslav@557: int nn = (int) Math.min(n, maxSkipBufferSize); jaroslav@557: synchronized (lock) { jaroslav@557: if ((skipBuffer == null) || (skipBuffer.length < nn)) jaroslav@557: skipBuffer = new char[nn]; jaroslav@557: long r = n; jaroslav@557: while (r > 0) { jaroslav@557: int nc = read(skipBuffer, 0, (int)Math.min(r, nn)); jaroslav@557: if (nc == -1) jaroslav@557: break; jaroslav@557: r -= nc; jaroslav@557: } jaroslav@557: return n - r; jaroslav@557: } jaroslav@557: } jaroslav@557: jaroslav@557: /** jaroslav@557: * Tells whether this stream is ready to be read. jaroslav@557: * jaroslav@557: * @return True if the next read() is guaranteed not to block for input, jaroslav@557: * false otherwise. Note that returning false does not guarantee that the jaroslav@557: * next read will block. jaroslav@557: * jaroslav@557: * @exception IOException If an I/O error occurs jaroslav@557: */ jaroslav@557: public boolean ready() throws IOException { jaroslav@557: return false; jaroslav@557: } jaroslav@557: jaroslav@557: /** jaroslav@557: * Tells whether this stream supports the mark() operation. The default jaroslav@557: * implementation always returns false. Subclasses should override this jaroslav@557: * method. jaroslav@557: * jaroslav@557: * @return true if and only if this stream supports the mark operation. jaroslav@557: */ jaroslav@557: public boolean markSupported() { jaroslav@557: return false; jaroslav@557: } jaroslav@557: jaroslav@557: /** jaroslav@557: * Marks the present position in the stream. Subsequent calls to reset() jaroslav@557: * will attempt to reposition the stream to this point. Not all jaroslav@557: * character-input streams support the mark() operation. jaroslav@557: * jaroslav@557: * @param readAheadLimit Limit on the number of characters that may be jaroslav@557: * read while still preserving the mark. After jaroslav@557: * reading this many characters, attempting to jaroslav@557: * reset the stream may fail. jaroslav@557: * jaroslav@557: * @exception IOException If the stream does not support mark(), jaroslav@557: * or if some other I/O error occurs jaroslav@557: */ jaroslav@557: public void mark(int readAheadLimit) throws IOException { jaroslav@557: throw new IOException("mark() not supported"); jaroslav@557: } jaroslav@557: jaroslav@557: /** jaroslav@557: * Resets the stream. If the stream has been marked, then attempt to jaroslav@557: * reposition it at the mark. If the stream has not been marked, then jaroslav@557: * attempt to reset it in some way appropriate to the particular stream, jaroslav@557: * for example by repositioning it to its starting point. Not all jaroslav@557: * character-input streams support the reset() operation, and some support jaroslav@557: * reset() without supporting mark(). jaroslav@557: * jaroslav@557: * @exception IOException If the stream has not been marked, jaroslav@557: * or if the mark has been invalidated, jaroslav@557: * or if the stream does not support reset(), jaroslav@557: * or if some other I/O error occurs jaroslav@557: */ jaroslav@557: public void reset() throws IOException { jaroslav@557: throw new IOException("reset() not supported"); jaroslav@557: } jaroslav@557: jaroslav@557: /** jaroslav@557: * Closes the stream and releases any system resources associated with jaroslav@557: * it. Once the stream has been closed, further read(), ready(), jaroslav@557: * mark(), reset(), or skip() invocations will throw an IOException. jaroslav@557: * Closing a previously closed stream has no effect. jaroslav@557: * jaroslav@557: * @exception IOException If an I/O error occurs jaroslav@557: */ jaroslav@557: abstract public void close() throws IOException; jaroslav@557: jaroslav@557: }