1 /*
  2  * Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.io;
 27 
 28 
 29 import java.nio.CharBuffer;
 30 import java.nio.ReadOnlyBufferException;
 31 import java.util.Objects;
 32 
 33 /**
 34  * Abstract class for reading character streams.  The only methods that a
 35  * subclass must implement are read(char[], int, int) and close().  Most
 36  * subclasses, however, will override some of the methods defined here in order
 37  * to provide higher efficiency, additional functionality, or both.
 38  *
 39  *
 40  * @see BufferedReader
 41  * @see   LineNumberReader
 42  * @see CharArrayReader
 43  * @see InputStreamReader
 44  * @see   FileReader
 45  * @see FilterReader
 46  * @see   PushbackReader
 47  * @see PipedReader
 48  * @see StringReader
 49  * @see Writer
 50  *
 51  * @author      Mark Reinhold
 52  * @since       1.1
 53  */
 54 
 55 public abstract class Reader implements Readable, Closeable {
 56 
 57     private static final int TRANSFER_BUFFER_SIZE = 8192;
 58 
 59     /**
 60      * Returns a new {@code Reader} that reads no characters. The returned
 61      * stream is initially open.  The stream is closed by calling the
 62      * {@code close()} method.  Subsequent calls to {@code close()} have no
 63      * effect.
 64      *
 65      * <p> While the stream is open, the {@code read()}, {@code read(char[])},
 66      * {@code read(char[], int, int)}, {@code read(CharBuffer)}, {@code
 67      * ready()}, {@code skip(long)}, and {@code transferTo()} methods all
 68      * behave as if end of stream has been reached. After the stream has been
 69      * closed, these methods all throw {@code IOException}.
 70      *
 71      * <p> The {@code markSupported()} method returns {@code false}.  The
 72      * {@code mark()} and {@code reset()} methods throw an {@code IOException}.
 73      *
 74      * <p> The {@link #lock object} used to synchronize operations on the
 75      * returned {@code Reader} is not specified.
 76      *
 77      * @return a {@code Reader} which reads no characters
 78      *
 79      * @since 11
 80      */
 81     public static Reader nullReader() {
 82         return new Reader() {
 83             private volatile boolean closed;
 84 
 85             private void ensureOpen() throws IOException {
 86                 if (closed) {
 87                     throw new IOException("Stream closed");
 88                 }
 89             }
 90 
 91             @Override
 92             public int read() throws IOException {
 93                 ensureOpen();
 94                 return -1;
 95             }
 96 
 97             @Override
 98             public int read(char[] cbuf, int off, int len) throws IOException {
 99                 Objects.checkFromIndexSize(off, len, cbuf.length);
100                 ensureOpen();
101                 if (len == 0) {
102                     return 0;
103                 }
104                 return -1;
105             }
106 
107             @Override
108             public int read(CharBuffer target) throws IOException {
109                 Objects.requireNonNull(target);
110                 ensureOpen();
111                 if (target.hasRemaining()) {
112                     return -1;
113                 }
114                 return 0;
115             }
116 
117             @Override
118             public boolean ready() throws IOException {
119                 ensureOpen();
120                 return false;
121             }
122 
123             @Override
124             public long skip(long n) throws IOException {
125                 ensureOpen();
126                 return 0L;
127             }
128 
129             @Override
130             public long transferTo(Writer out) throws IOException {
131                 Objects.requireNonNull(out);
132                 ensureOpen();
133                 return 0L;
134             }
135 
136             @Override
137             public void close() {
138                 closed = true;
139             }
140         };
141     }
142 
143     /**
144      * The object used to synchronize operations on this stream.  For
145      * efficiency, a character-stream object may use an object other than
146      * itself to protect critical sections.  A subclass should therefore use
147      * the object in this field rather than {@code this} or a synchronized
148      * method.
149      */
150     protected Object lock;
151 
152     /**
153      * Creates a new character-stream reader whose critical sections will
154      * synchronize on the reader itself.
155      */
156     protected Reader() {
157         this.lock = this;
158     }
159 
160     /**
161      * Creates a new character-stream reader whose critical sections will
162      * synchronize on the given object.
163      *
164      * @param lock  The Object to synchronize on.
165      */
166     protected Reader(Object lock) {
167         if (lock == null) {
168             throw new NullPointerException();
169         }
170         this.lock = lock;
171     }
172 
173     /**
174      * Attempts to read characters into the specified character buffer.
175      * The buffer is used as a repository of characters as-is: the only
176      * changes made are the results of a put operation. No flipping or
177      * rewinding of the buffer is performed.
178      *
179      * @param target the buffer to read characters into
180      * @return The number of characters added to the buffer, or
181      *         -1 if this source of characters is at its end
182      * @throws IOException if an I/O error occurs
183      * @throws NullPointerException if target is null
184      * @throws java.nio.ReadOnlyBufferException if target is a read only buffer
185      * @since 1.5
186      */
187     public int read(CharBuffer target) throws IOException {
188         if (target.isReadOnly())
189             throw new ReadOnlyBufferException();
190 
191         int nread;
192         if (target.hasArray()) {
193             char[] cbuf = target.array();
194             int pos = target.position();
195             int rem = Math.max(target.limit() - pos, 0);
196             int off = target.arrayOffset() + pos;
197             nread = this.read(cbuf, off, rem);
198             if (nread > 0)
199                 target.position(pos + nread);
200         } else {
201             int len = target.remaining();
202             char[] cbuf = new char[len];
203             nread = read(cbuf, 0, len);
204             if (nread > 0)
205                 target.put(cbuf, 0, nread);
206         }
207         return nread;
208     }
209 
210     /**
211      * Reads a single character.  This method will block until a character is
212      * available, an I/O error occurs, or the end of the stream is reached.
213      *
214      * <p> Subclasses that intend to support efficient single-character input
215      * should override this method.
216      *
217      * @return     The character read, as an integer in the range 0 to 65535
218      *             ({@code 0x00-0xffff}), or -1 if the end of the stream has
219      *             been reached
220      *
221      * @throws     IOException  If an I/O error occurs
222      */
223     public int read() throws IOException {
224         char[] cb = new char[1];
225         if (read(cb, 0, 1) == -1)
226             return -1;
227         else
228             return cb[0];
229     }
230 
231     /**
232      * Reads characters into an array.  This method will block until some input
233      * is available, an I/O error occurs, or the end of the stream is reached.
234      *
235      * <p> If the length of {@code cbuf} is zero, then no characters are read
236      * and {@code 0} is returned; otherwise, there is an attempt to read at
237      * least one character.  If no character is available because the stream is
238      * at its end, the value {@code -1} is returned; otherwise, at least one
239      * character is read and stored into {@code cbuf}.
240      *
241      * @param       cbuf  Destination buffer
242      *
243      * @return      The number of characters read, or -1
244      *              if the end of the stream
245      *              has been reached
246      *
247      * @throws      IOException  If an I/O error occurs
248      */
249     public int read(char[] cbuf) throws IOException {
250         return read(cbuf, 0, cbuf.length);
251     }
252 
253     /**
254      * Reads characters into a portion of an array.  This method will block
255      * until some input is available, an I/O error occurs, or the end of the
256      * stream is reached.
257      *
258      * <p> If {@code len} is zero, then no characters are read and {@code 0} is
259      * returned; otherwise, there is an attempt to read at least one character.
260      * If no character is available because the stream is at its end, the value
261      * {@code -1} is returned; otherwise, at least one character is read and
262      * stored into {@code cbuf}.
263      *
264      * @param      cbuf  Destination buffer
265      * @param      off   Offset at which to start storing characters
266      * @param      len   Maximum number of characters to read
267      *
268      * @return     The number of characters read, or -1 if the end of the
269      *             stream has been reached
270      *
271      * @throws     IndexOutOfBoundsException
272      *             If {@code off} is negative, or {@code len} is negative,
273      *             or {@code len} is greater than {@code cbuf.length - off}
274      * @throws     IOException  If an I/O error occurs
275      */
276     public abstract int read(char[] cbuf, int off, int len) throws IOException;
277 
278     /** Maximum skip-buffer size */
279     private static final int maxSkipBufferSize = 8192;
280 
281     /** Skip buffer, null until allocated */
282     private char[] skipBuffer = null;
283 
284     /**
285      * Skips characters.  This method will block until some characters are
286      * available, an I/O error occurs, or the end of the stream is reached.
287      * If the stream is already at its end before this method is invoked,
288      * then no characters are skipped and zero is returned.
289      *
290      * @param  n  The number of characters to skip
291      *
292      * @return    The number of characters actually skipped
293      *
294      * @throws     IllegalArgumentException  If {@code n} is negative.
295      * @throws     IOException  If an I/O error occurs
296      */
297     public long skip(long n) throws IOException {
298         if (n < 0L)
299             throw new IllegalArgumentException("skip value is negative");
300         int nn = (int) Math.min(n, maxSkipBufferSize);
301         synchronized (lock) {
302             if ((skipBuffer == null) || (skipBuffer.length < nn))
303                 skipBuffer = new char[nn];
304             long r = n;
305             while (r > 0) {
306                 int nc = read(skipBuffer, 0, (int)Math.min(r, nn));
307                 if (nc == -1)
308                     break;
309                 r -= nc;
310             }
311             return n - r;
312         }
313     }
314 
315     /**
316      * Tells whether this stream is ready to be read.
317      *
318      * @return True if the next read() is guaranteed not to block for input,
319      * false otherwise.  Note that returning false does not guarantee that the
320      * next read will block.
321      *
322      * @throws     IOException  If an I/O error occurs
323      */
324     public boolean ready() throws IOException {
325         return false;
326     }
327 
328     /**
329      * Tells whether this stream supports the mark() operation. The default
330      * implementation always returns false. Subclasses should override this
331      * method.
332      *
333      * @return true if and only if this stream supports the mark operation.
334      */
335     public boolean markSupported() {
336         return false;
337     }
338 
339     /**
340      * Marks the present position in the stream.  Subsequent calls to reset()
341      * will attempt to reposition the stream to this point.  Not all
342      * character-input streams support the mark() operation.
343      *
344      * @param  readAheadLimit  Limit on the number of characters that may be
345      *                         read while still preserving the mark.  After
346      *                         reading this many characters, attempting to
347      *                         reset the stream may fail.
348      *
349      * @throws     IOException  If the stream does not support mark(),
350      *                          or if some other I/O error occurs
351      */
352     public void mark(int readAheadLimit) throws IOException {
353         throw new IOException("mark() not supported");
354     }
355 
356     /**
357      * Resets the stream.  If the stream has been marked, then attempt to
358      * reposition it at the mark.  If the stream has not been marked, then
359      * attempt to reset it in some way appropriate to the particular stream,
360      * for example by repositioning it to its starting point.  Not all
361      * character-input streams support the reset() operation, and some support
362      * reset() without supporting mark().
363      *
364      * @throws     IOException  If the stream has not been marked,
365      *                          or if the mark has been invalidated,
366      *                          or if the stream does not support reset(),
367      *                          or if some other I/O error occurs
368      */
369     public void reset() throws IOException {
370         throw new IOException("reset() not supported");
371     }
372 
373     /**
374      * Closes the stream and releases any system resources associated with
375      * it.  Once the stream has been closed, further read(), ready(),
376      * mark(), reset(), or skip() invocations will throw an IOException.
377      * Closing a previously closed stream has no effect.
378      *
379      * @throws     IOException  If an I/O error occurs
380      */
381      public abstract void close() throws IOException;
382 
383     /**
384      * Reads all characters from this reader and writes the characters to the
385      * given writer in the order that they are read. On return, this reader
386      * will be at end of the stream. This method does not close either reader
387      * or writer.
388      * <p>
389      * This method may block indefinitely reading from the reader, or
390      * writing to the writer. The behavior for the case where the reader
391      * and/or writer is <i>asynchronously closed</i>, or the thread
392      * interrupted during the transfer, is highly reader and writer
393      * specific, and therefore not specified.
394      * <p>
395      * If an I/O error occurs reading from the reader or writing to the
396      * writer, then it may do so after some characters have been read or
397      * written. Consequently the reader may not be at end of the stream and
398      * one, or both, streams may be in an inconsistent state. It is strongly
399      * recommended that both streams be promptly closed if an I/O error occurs.
400      *
401      * @param  out the writer, non-null
402      * @return the number of characters transferred
403      * @throws IOException if an I/O error occurs when reading or writing
404      * @throws NullPointerException if {@code out} is {@code null}
405      *
406      * @since 10
407      */
408     public long transferTo(Writer out) throws IOException {
409         Objects.requireNonNull(out, "out");
410         long transferred = 0;
411         char[] buffer = new char[TRANSFER_BUFFER_SIZE];
412         int nRead;
413         while ((nRead = read(buffer, 0, TRANSFER_BUFFER_SIZE)) >= 0) {
414             out.write(buffer, 0, nRead);
415             transferred += nRead;
416         }
417         return transferred;
418     }
419 
420 }