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: }