/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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; /** * Reader is an Abstract class for reading Character Streams. Subclasses of * Reader must implement the methods read(char[], int, int) and * close(). * * @see Writer */ public abstract class Reader { /** * The object used to synchronize access to the reader. */ protected Object lock; /** * Constructs a new character stream Reader using this as the * Object to synchronize critical regions around. */ protected Reader() { super(); lock = this; } /** * Constructs a new character stream Reader using lock as the * Object to synchronize critical regions around. * * @param lock * the Object to synchronize critical regions * around. */ protected Reader(Object lock) { if (lock == null) { throw new NullPointerException(); } this.lock = lock; } /** * Close this Reader. This must be implemented by any concrete subclasses. * The implementation should free any resources associated with the Reader. * * @throws IOException * If an error occurs attempting to close this Reader. */ public abstract void close() throws IOException; /** * Set a Mark position in this Reader. The parameter readLimit * indicates how many characters can be read before a mark is invalidated. * Sending reset() will reposition the reader back to the marked position * provided readLimit has not been surpassed. *

* This default implementation simply throws IOException and concrete * subclasses must provide their own implementations. * * @param readLimit * an int representing how many characters must be read before * invalidating the mark. * * @throws IOException * If an error occurs attempting mark this Reader. */ public void mark(int readLimit) throws IOException { throw new IOException(); } /** * Answers a boolean indicating whether or not this Reader supports mark() * and reset(). This class a default implementation which answers false. * * @return true if mark() and reset() are supported, * false otherwise. This implementation returns * false. */ public boolean markSupported() { return false; } /** * Reads a single character from this reader and returns the result as an * int. The 2 higher-order characters are set to 0. If the end of reader was * encountered then return -1. * * @return the character read or -1 if end of reader. * * @throws IOException * If the Reader is already closed or some other IO error * occurs. */ public int read() throws IOException { synchronized (lock) { char charArray[] = new char[1]; if (read(charArray, 0, 1) != -1) { return charArray[0]; } return -1; } } /** * Reads characters from this Reader and stores them in the character array * buf starting at offset 0. Returns the number of characters * actually read or -1 if the end of reader was encountered. * * @param buf * character array to store the read characters * @return how many characters were successfully read in or else -1 if the * end of the reader was detected. * * @throws IOException * If the Reader is already closed or some other IO error * occurs. */ public int read(char buf[]) throws IOException { return read(buf, 0, buf.length); } /** * Reads at most count characters from this Reader and stores * them at offset in the character array buf. * Returns the number of characters actually read or -1 if the end of reader * was encountered. * * @param buf * character array to store the read characters * @param offset * offset in buf to store the read characters * @param count * how many characters should be read in * @return how many characters were successfully read in or else -1 if the * end of the reader was detected. * * @throws IOException * If the Reader is already closed or some other IO error * occurs. */ public abstract int read(char buf[], int offset, int count) throws IOException; /** * Answers a boolean indicating whether or not this Reader is * ready to be read without blocking. If the result is true, * the next read() will not block. If the result is * false this Reader may or may not block when * read() is sent. * * @return true if the receiver will not block when * read() is called, false if unknown * or blocking will occur. * * @throws IOException * If the Reader is already closed or some other IO error * occurs. */ public boolean ready() throws IOException { return false; } /** * Reset this Readers position to the last mark() location. * Invocations of read()/skip() will occur from this new * location. If this Reader was not marked, the implementation of * reset() is implementation specific. See the comment for * the specific Reader subclass for implementation details. The default * action is to throw IOException. * * @throws IOException * If a problem occured or the receiver does not support * mark()/reset(). */ public void reset() throws IOException { throw new IOException(); } /** * Skips count number of characters in this Reader. * Subsequent read()'s will not return these characters * unless reset() is used. This method may perform multiple * reads to read count characters. * * @param count * how many characters should be passed over * @return how many characters were successfully passed over * * @throws IOException * If the Reader is closed when the call is made or if an IO * error occurs during the operation. */ public long skip(long count) throws IOException { if (count < 0) { throw new IllegalArgumentException(); } synchronized (lock) { long skipped = 0; int toRead = count < 512 ? (int) count : 512; char charsSkipped[] = new char[toRead]; while (skipped < count) { int read = read(charsSkipped, 0, toRead); if (read == -1) { return skipped; } skipped += read; if (read < toRead) { return skipped; } if (count - skipped < toRead) { toRead = (int) (count - skipped); } } return skipped; } } }