| /* |
| * 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; |
| |
| import java.nio.CharBuffer; |
| import java.nio.ReadOnlyBufferException; |
| |
| /** |
| * The base class for all readers. A reader is a means of reading data from a |
| * source in a character-wise manner. Some readers also support marking a |
| * position in the input and returning to this position later. |
| * <p> |
| * This abstract class does not provide a fully working implementation, so it |
| * needs to be subclassed, and at least the {@link #read(char[], int, int)} and |
| * {@link #close()} methods needs to be overridden. Overriding some of the |
| * non-abstract methods is also often advised, since it might result in higher |
| * efficiency. |
| * <p> |
| * Many specialized readers for purposes like reading from a file already exist |
| * in this package. |
| * |
| * @see Writer |
| */ |
| public abstract class Reader implements Readable, Closeable { |
| /** |
| * The object used to synchronize access to the reader. |
| */ |
| protected Object lock; |
| |
| /** |
| * Constructs a new {@code Reader} with {@code this} as the object used to |
| * synchronize critical sections. |
| */ |
| protected Reader() { |
| lock = this; |
| } |
| |
| /** |
| * Constructs a new {@code Reader} with {@code lock} used to synchronize |
| * critical sections. |
| * |
| * @param lock |
| * the {@code Object} used to synchronize critical sections. |
| * @throws NullPointerException |
| * if {@code lock} is {@code null}. |
| */ |
| protected Reader(Object lock) { |
| if (lock == null) { |
| throw new NullPointerException("lock == null"); |
| } |
| this.lock = lock; |
| } |
| |
| /** |
| * Closes this reader. Implementations of this method should free any |
| * resources associated with the reader. |
| * |
| * @throws IOException |
| * if an error occurs while closing this reader. |
| */ |
| public abstract void close() throws IOException; |
| |
| /** |
| * Sets a mark position in this reader. The parameter {@code readLimit} |
| * indicates how many characters can be read before the mark is invalidated. |
| * Calling {@code reset()} will reposition the reader back to the marked |
| * position if {@code readLimit} has not been surpassed. |
| * <p> |
| * This default implementation simply throws an {@code IOException}; |
| * subclasses must provide their own implementation. |
| * |
| * @param readLimit |
| * the number of characters that can be read before the mark is |
| * invalidated. |
| * @throws IllegalArgumentException |
| * if {@code readLimit < 0}. |
| * @throws IOException |
| * if an error occurs while setting a mark in this reader. |
| * @see #markSupported() |
| * @see #reset() |
| */ |
| public void mark(int readLimit) throws IOException { |
| throw new IOException(); |
| } |
| |
| /** |
| * Indicates whether this reader supports the {@code mark()} and |
| * {@code reset()} methods. This default implementation returns |
| * {@code false}. |
| * |
| * @return always {@code false}. |
| */ |
| public boolean markSupported() { |
| return false; |
| } |
| |
| /** |
| * Reads a single character from this reader and returns it as an integer |
| * with the two higher-order bytes set to 0. Returns -1 if the end of the |
| * reader has been reached. |
| * |
| * @return the character read or -1 if the end of the reader has been |
| * reached. |
| * @throws IOException |
| * if this reader is closed or some other I/O 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 |
| * {@code buf} starting at offset 0. Returns the number of characters |
| * actually read or -1 if the end of the reader has been reached. |
| * |
| * @param buf |
| * character array to store the characters read. |
| * @return the number of characters read or -1 if the end of the reader has |
| * been reached. |
| * @throws IOException |
| * if this reader is closed or some other I/O error occurs. |
| */ |
| public int read(char[] buf) throws IOException { |
| return read(buf, 0, buf.length); |
| } |
| |
| /** |
| * Reads at most {@code count} characters from this reader and stores them |
| * at {@code offset} in the character array {@code buf}. Returns the number |
| * of characters actually read or -1 if the end of the reader has been |
| * reached. |
| * |
| * @param buf |
| * the character array to store the characters read. |
| * @param offset |
| * the initial position in {@code buffer} to store the characters |
| * read from this reader. |
| * @param count |
| * the maximum number of characters to read. |
| * @return the number of characters read or -1 if the end of the reader has |
| * been reached. |
| * @throws IOException |
| * if this reader is closed or some other I/O error occurs. |
| */ |
| public abstract int read(char[] buf, int offset, int count) throws IOException; |
| |
| /** |
| * Indicates whether this reader is ready to be read without blocking. |
| * Returns {@code true} if this reader will not block when {@code read} is |
| * called, {@code false} if unknown or blocking will occur. This default |
| * implementation always returns {@code false}. |
| * |
| * @return always {@code false}. |
| * @throws IOException |
| * if this reader is closed or some other I/O error occurs. |
| * @see #read() |
| * @see #read(char[]) |
| * @see #read(char[], int, int) |
| */ |
| public boolean ready() throws IOException { |
| return false; |
| } |
| |
| /** |
| * Resets this reader's position to the last {@code mark()} location. |
| * Invocations of {@code read()} and {@code skip()} will occur from this new |
| * location. If this reader has not been marked, the behavior of |
| * {@code reset()} is implementation specific. This default |
| * implementation throws an {@code IOException}. |
| * |
| * @throws IOException |
| * always thrown in this default implementation. |
| * @see #mark(int) |
| * @see #markSupported() |
| */ |
| public void reset() throws IOException { |
| throw new IOException(); |
| } |
| |
| /** |
| * Skips {@code charCount} characters in this reader. Subsequent calls of |
| * {@code read} methods will not return these characters unless {@code |
| * reset} is used. This method may perform multiple reads to read {@code |
| * charCount} characters. |
| * |
| * @return the number of characters actually skipped. |
| * @throws IllegalArgumentException |
| * if {@code charCount < 0}. |
| * @throws IOException |
| * if this reader is closed or some other I/O error occurs. |
| * @see #mark(int) |
| * @see #markSupported() |
| * @see #reset() |
| */ |
| public long skip(long charCount) throws IOException { |
| if (charCount < 0) { |
| throw new IllegalArgumentException("charCount < 0: " + charCount); |
| } |
| synchronized (lock) { |
| long skipped = 0; |
| int toRead = charCount < 512 ? (int) charCount : 512; |
| char[] charsSkipped = new char[toRead]; |
| while (skipped < charCount) { |
| int read = read(charsSkipped, 0, toRead); |
| if (read == -1) { |
| return skipped; |
| } |
| skipped += read; |
| if (read < toRead) { |
| return skipped; |
| } |
| if (charCount - skipped < toRead) { |
| toRead = (int) (charCount - skipped); |
| } |
| } |
| return skipped; |
| } |
| } |
| |
| /** |
| * Reads characters and puts them into the {@code target} character buffer. |
| * |
| * @param target |
| * the destination character buffer. |
| * @return the number of characters put into {@code target} or -1 if the end |
| * of this reader has been reached before a character has been read. |
| * @throws IOException |
| * if any I/O error occurs while reading from this reader. |
| * @throws NullPointerException |
| * if {@code target} is {@code null}. |
| * @throws ReadOnlyBufferException |
| * if {@code target} is read-only. |
| */ |
| public int read(CharBuffer target) throws IOException { |
| int length = target.length(); |
| char[] buf = new char[length]; |
| length = Math.min(length, read(buf)); |
| if (length > 0) { |
| target.put(buf, 0, length); |
| } |
| return length; |
| } |
| } |