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 lock = this; 51 } 52 53 /** 54 * Constructs a new {@code Reader} with {@code lock} used to synchronize 55 * critical sections. 56 * 57 * @param lock 58 * the {@code Object} used to synchronize critical sections. 59 * @throws NullPointerException 60 * if {@code lock} is {@code null}. 61 */ 62 protected Reader(Object lock) { 63 if (lock == null) { 64 throw new NullPointerException("lock == null"); 65 } 66 this.lock = lock; 67 } 68 69 /** 70 * Closes this reader. Implementations of this method should free any 71 * resources associated with the reader. 72 * 73 * @throws IOException 74 * if an error occurs while closing this reader. 75 */ 76 public abstract void close() throws IOException; 77 78 /** 79 * Sets a mark position in this reader. The parameter {@code readLimit} 80 * indicates how many characters can be read before the mark is invalidated. 81 * Calling {@code reset()} will reposition the reader back to the marked 82 * position if {@code readLimit} has not been surpassed. 83 * <p> 84 * This default implementation simply throws an {@code IOException}; 85 * subclasses must provide their own implementation. 86 * 87 * @param readLimit 88 * the number of characters that can be read before the mark is 89 * invalidated. 90 * @throws IllegalArgumentException 91 * if {@code readLimit < 0}. 92 * @throws IOException 93 * if an error occurs while setting a mark in this reader. 94 * @see #markSupported() 95 * @see #reset() 96 */ 97 public void mark(int readLimit) throws IOException { 98 throw new IOException(); 99 } 100 101 /** 102 * Indicates whether this reader supports the {@code mark()} and 103 * {@code reset()} methods. This default implementation returns 104 * {@code false}. 105 * 106 * @return always {@code false}. 107 */ 108 public boolean markSupported() { 109 return false; 110 } 111 112 /** 113 * Reads a single character from this reader and returns it as an integer 114 * with the two higher-order bytes set to 0. Returns -1 if the end of the 115 * reader has been reached. 116 * 117 * @return the character read or -1 if the end of the reader has been 118 * reached. 119 * @throws IOException 120 * if this reader is closed or some other I/O error occurs. 121 */ 122 public int read() throws IOException { 123 synchronized (lock) { 124 char[] charArray = new char[1]; 125 if (read(charArray, 0, 1) != -1) { 126 return charArray[0]; 127 } 128 return -1; 129 } 130 } 131 132 /** 133 * Reads characters from this reader and stores them in the character array 134 * {@code buf} starting at offset 0. Returns the number of characters 135 * actually read or -1 if the end of the reader has been reached. 136 * 137 * @param buf 138 * character array to store the characters read. 139 * @return the number of characters read or -1 if the end of the reader has 140 * been reached. 141 * @throws IOException 142 * if this reader is closed or some other I/O error occurs. 143 */ 144 public int read(char[] buf) throws IOException { 145 return read(buf, 0, buf.length); 146 } 147 148 /** 149 * Reads at most {@code count} characters from this reader and stores them 150 * at {@code offset} in the character array {@code buf}. Returns the number 151 * of characters actually read or -1 if the end of the reader has been 152 * reached. 153 * 154 * @param buf 155 * the character array to store the characters read. 156 * @param offset 157 * the initial position in {@code buffer} to store the characters 158 * read from this reader. 159 * @param count 160 * the maximum number of characters to read. 161 * @return the number of characters read or -1 if the end of the reader has 162 * been reached. 163 * @throws IOException 164 * if this reader is closed or some other I/O error occurs. 165 */ 166 public abstract int read(char[] buf, int offset, int count) throws IOException; 167 168 /** 169 * Indicates whether this reader is ready to be read without blocking. 170 * Returns {@code true} if this reader will not block when {@code read} is 171 * called, {@code false} if unknown or blocking will occur. This default 172 * implementation always returns {@code false}. 173 * 174 * @return always {@code false}. 175 * @throws IOException 176 * if this reader is closed or some other I/O error occurs. 177 * @see #read() 178 * @see #read(char[]) 179 * @see #read(char[], int, int) 180 */ 181 public boolean ready() throws IOException { 182 return false; 183 } 184 185 /** 186 * Resets this reader's position to the last {@code mark()} location. 187 * Invocations of {@code read()} and {@code skip()} will occur from this new 188 * location. If this reader has not been marked, the behavior of 189 * {@code reset()} is implementation specific. This default 190 * implementation throws an {@code IOException}. 191 * 192 * @throws IOException 193 * always thrown in this default implementation. 194 * @see #mark(int) 195 * @see #markSupported() 196 */ 197 public void reset() throws IOException { 198 throw new IOException(); 199 } 200 201 /** 202 * Skips {@code charCount} characters in this reader. Subsequent calls of 203 * {@code read} methods will not return these characters unless {@code 204 * reset} is used. This method may perform multiple reads to read {@code 205 * charCount} characters. 206 * 207 * @return the number of characters actually skipped. 208 * @throws IllegalArgumentException 209 * if {@code charCount < 0}. 210 * @throws IOException 211 * if this reader is closed or some other I/O error occurs. 212 * @see #mark(int) 213 * @see #markSupported() 214 * @see #reset() 215 */ 216 public long skip(long charCount) throws IOException { 217 if (charCount < 0) { 218 throw new IllegalArgumentException("charCount < 0: " + charCount); 219 } 220 synchronized (lock) { 221 long skipped = 0; 222 int toRead = charCount < 512 ? (int) charCount : 512; 223 char[] charsSkipped = new char[toRead]; 224 while (skipped < charCount) { 225 int read = read(charsSkipped, 0, toRead); 226 if (read == -1) { 227 return skipped; 228 } 229 skipped += read; 230 if (read < toRead) { 231 return skipped; 232 } 233 if (charCount - skipped < toRead) { 234 toRead = (int) (charCount - skipped); 235 } 236 } 237 return skipped; 238 } 239 } 240 241 /** 242 * Reads characters and puts them into the {@code target} character buffer. 243 * 244 * @param target 245 * the destination character buffer. 246 * @return the number of characters put into {@code target} or -1 if the end 247 * of this reader has been reached before a character has been read. 248 * @throws IOException 249 * if any I/O error occurs while reading from this reader. 250 * @throws NullPointerException 251 * if {@code target} is {@code null}. 252 * @throws ReadOnlyBufferException 253 * if {@code target} is read-only. 254 */ 255 public int read(CharBuffer target) throws IOException { 256 int length = target.length(); 257 char[] buf = new char[length]; 258 length = Math.min(length, read(buf)); 259 if (length > 0) { 260 target.put(buf, 0, length); 261 } 262 return length; 263 } 264} 265