Reader.java revision f9480f317cddcec859025833b748f096247a40aa
1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package java.io;
19
20import java.nio.CharBuffer;
21import java.nio.ReadOnlyBufferException;
22
23/**
24 * The base class for all readers. A reader is a means of reading data from a
25 * source in a character-wise manner. Some readers also support marking a
26 * position in the input and returning to this position later.
27 * <p>
28 * This abstract class does not provide a fully working implementation, so it
29 * needs to be subclassed, and at least the {@link #read(char[], int, int)} and
30 * {@link #close()} methods needs to be overridden. Overriding some of the
31 * non-abstract methods is also often advised, since it might result in higher
32 * efficiency.
33 * <p>
34 * Many specialized readers for purposes like reading from a file already exist
35 * in this package.
36 *
37 * @see Writer
38 */
39public abstract class Reader implements Readable, Closeable {
40    /**
41     * The object used to synchronize access to the reader.
42     */
43    protected Object lock;
44
45    /**
46     * Constructs a new {@code Reader} with {@code this} as the object used to
47     * synchronize critical sections.
48     */
49    protected Reader() {
50        super();
51        lock = this;
52    }
53
54    /**
55     * Constructs a new {@code Reader} with {@code lock} used to synchronize
56     * critical sections.
57     *
58     * @param lock
59     *            the {@code Object} used to synchronize critical sections.
60     * @throws NullPointerException
61     *             if {@code lock} is {@code null}.
62     */
63    protected Reader(Object lock) {
64        if (lock == null) {
65            throw new NullPointerException();
66        }
67        this.lock = lock;
68    }
69
70    /**
71     * Closes this reader. Implementations of this method should free any
72     * resources associated with the reader.
73     *
74     * @throws IOException
75     *             if an error occurs while closing this reader.
76     */
77    public abstract void close() throws IOException;
78
79    /**
80     * Sets a mark position in this reader. The parameter {@code readLimit}
81     * indicates how many characters can be read before the mark is invalidated.
82     * Calling {@code reset()} will reposition the reader back to the marked
83     * position if {@code readLimit} has not been surpassed.
84     * <p>
85     * This default implementation simply throws an {@code IOException};
86     * subclasses must provide their own implementation.
87     *
88     * @param readLimit
89     *            the number of characters that can be read before the mark is
90     *            invalidated.
91     * @throws IllegalArgumentException
92     *             if {@code readLimit < 0}.
93     * @throws IOException
94     *             if an error occurs while setting a mark in this reader.
95     * @see #markSupported()
96     * @see #reset()
97     */
98    public void mark(int readLimit) throws IOException {
99        throw new IOException();
100    }
101
102    /**
103     * Indicates whether this reader supports the {@code mark()} and
104     * {@code reset()} methods. This default implementation returns
105     * {@code false}.
106     *
107     * @return always {@code false}.
108     */
109    public boolean markSupported() {
110        return false;
111    }
112
113    /**
114     * Reads a single character from this reader and returns it as an integer
115     * with the two higher-order bytes set to 0. Returns -1 if the end of the
116     * reader has been reached.
117     *
118     * @return the character read or -1 if the end of the reader has been
119     *         reached.
120     * @throws IOException
121     *             if this reader is closed or some other I/O error occurs.
122     */
123    public int read() throws IOException {
124        synchronized (lock) {
125            char[] charArray = new char[1];
126            if (read(charArray, 0, 1) != -1) {
127                return charArray[0];
128            }
129            return -1;
130        }
131    }
132
133    /**
134     * Reads characters from this reader and stores them in the character array
135     * {@code buf} starting at offset 0. Returns the number of characters
136     * actually read or -1 if the end of the reader has been reached.
137     *
138     * @param buf
139     *            character array to store the characters read.
140     * @return the number of characters read or -1 if the end of the reader has
141     *         been reached.
142     * @throws IOException
143     *             if this reader is closed or some other I/O error occurs.
144     */
145    public int read(char[] buf) throws IOException {
146        // BEGIN android-note
147        // changed array notation to be consistent with the rest of harmony
148        // END android-note
149        return read(buf, 0, buf.length);
150    }
151
152    /**
153     * Reads at most {@code count} characters from this reader and stores them
154     * at {@code offset} in the character array {@code buf}. Returns the number
155     * of characters actually read or -1 if the end of the reader has been
156     * reached.
157     *
158     * @param buf
159     *            the character array to store the characters read.
160     * @param offset
161     *            the initial position in {@code buffer} to store the characters
162     *            read from this reader.
163     * @param count
164     *            the maximum number of characters to read.
165     * @return the number of characters read or -1 if the end of the reader has
166     *         been reached.
167     * @throws IOException
168     *             if this reader is closed or some other I/O error occurs.
169     */
170    public abstract int read(char[] buf, int offset, int count)
171            throws IOException;
172    // BEGIN android-note
173    // changed array notation to be consistent with the rest of harmony
174    // END android-note
175
176    /**
177     * Indicates whether this reader is ready to be read without blocking.
178     * Returns {@code true} if this reader will not block when {@code read} is
179     * called, {@code false} if unknown or blocking will occur. This default
180     * implementation always returns {@code false}.
181     *
182     * @return always {@code false}.
183     * @throws IOException
184     *             if this reader is closed or some other I/O error occurs.
185     * @see #read()
186     * @see #read(char[])
187     * @see #read(char[], int, int)
188     */
189    public boolean ready() throws IOException {
190        return false;
191    }
192
193    /**
194     * Resets this reader's position to the last {@code mark()} location.
195     * Invocations of {@code read()} and {@code skip()} will occur from this new
196     * location. If this reader has not been marked, the behavior of
197     * {@code reset()} is implementation specific. This default
198     * implementation throws an {@code IOException}.
199     *
200     * @throws IOException
201     *             always thrown in this default implementation.
202     * @see #mark(int)
203     * @see #markSupported()
204     */
205    public void reset() throws IOException {
206        throw new IOException();
207    }
208
209    /**
210     * Skips {@code charCount} characters in this reader. Subsequent calls of
211     * {@code read} methods will not return these characters unless {@code
212     * reset} is used. This method may perform multiple reads to read {@code
213     * charCount} characters.
214     *
215     * @return the number of characters actually skipped.
216     * @throws IllegalArgumentException
217     *             if {@code charCount < 0}.
218     * @throws IOException
219     *             if this reader is closed or some other I/O error occurs.
220     * @see #mark(int)
221     * @see #markSupported()
222     * @see #reset()
223     */
224    public long skip(long charCount) throws IOException {
225        if (charCount < 0) {
226            throw new IllegalArgumentException("charCount < 0");
227        }
228        synchronized (lock) {
229            long skipped = 0;
230            int toRead = charCount < 512 ? (int) charCount : 512;
231            char[] charsSkipped = new char[toRead];
232            while (skipped < charCount) {
233                int read = read(charsSkipped, 0, toRead);
234                if (read == -1) {
235                    return skipped;
236                }
237                skipped += read;
238                if (read < toRead) {
239                    return skipped;
240                }
241                if (charCount - skipped < toRead) {
242                    toRead = (int) (charCount - skipped);
243                }
244            }
245            return skipped;
246        }
247    }
248
249    /**
250     * Reads characters and puts them into the {@code target} character buffer.
251     *
252     * @param target
253     *            the destination character buffer.
254     * @return the number of characters put into {@code target} or -1 if the end
255     *         of this reader has been reached before a character has been read.
256     * @throws IOException
257     *             if any I/O error occurs while reading from this reader.
258     * @throws NullPointerException
259     *             if {@code target} is {@code null}.
260     * @throws ReadOnlyBufferException
261     *             if {@code target} is read-only.
262     */
263    public int read(CharBuffer target) throws IOException {
264        if (null == target) {
265            throw new NullPointerException();
266        }
267        int length = target.length();
268        char[] buf = new char[length];
269        length = Math.min(length, read(buf));
270        if (length > 0) {
271            target.put(buf, 0, length);
272        }
273        return length;
274    }
275}
276