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 buffer} 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 * @throws IOException 138 * if this reader is closed or some other I/O error occurs. 139 */ 140 public int read(char[] buffer) throws IOException { 141 return read(buffer, 0, buffer.length); 142 } 143 144 /** 145 * Reads up to {@code count} characters from this reader and stores them 146 * at {@code offset} in the character array {@code buffer}. Returns the number 147 * of characters actually read or -1 if the end of the reader has been 148 * reached. 149 * 150 * @throws IOException 151 * if this reader is closed or some other I/O error occurs. 152 */ 153 public abstract int read(char[] buffer, int offset, int count) throws IOException; 154 155 /** 156 * Indicates whether this reader is ready to be read without blocking. 157 * Returns {@code true} if this reader will not block when {@code read} is 158 * called, {@code false} if unknown or blocking will occur. This default 159 * implementation always returns {@code false}. 160 * 161 * @return always {@code false}. 162 * @throws IOException 163 * if this reader is closed or some other I/O error occurs. 164 * @see #read() 165 * @see #read(char[]) 166 * @see #read(char[], int, int) 167 */ 168 public boolean ready() throws IOException { 169 return false; 170 } 171 172 /** 173 * Resets this reader's position to the last {@code mark()} location. 174 * Invocations of {@code read()} and {@code skip()} will occur from this new 175 * location. If this reader has not been marked, the behavior of 176 * {@code reset()} is implementation specific. This default 177 * implementation throws an {@code IOException}. 178 * 179 * @throws IOException 180 * always thrown in this default implementation. 181 * @see #mark(int) 182 * @see #markSupported() 183 */ 184 public void reset() throws IOException { 185 throw new IOException(); 186 } 187 188 /** 189 * Skips {@code charCount} characters in this reader. Subsequent calls of 190 * {@code read} methods will not return these characters unless {@code 191 * reset} is used. This method may perform multiple reads to read {@code 192 * charCount} characters. 193 * 194 * @return the number of characters actually skipped. 195 * @throws IllegalArgumentException 196 * if {@code charCount < 0}. 197 * @throws IOException 198 * if this reader is closed or some other I/O error occurs. 199 * @see #mark(int) 200 * @see #markSupported() 201 * @see #reset() 202 */ 203 public long skip(long charCount) throws IOException { 204 if (charCount < 0) { 205 throw new IllegalArgumentException("charCount < 0: " + charCount); 206 } 207 synchronized (lock) { 208 long skipped = 0; 209 int toRead = charCount < 512 ? (int) charCount : 512; 210 char[] charsSkipped = new char[toRead]; 211 while (skipped < charCount) { 212 int read = read(charsSkipped, 0, toRead); 213 if (read == -1) { 214 return skipped; 215 } 216 skipped += read; 217 if (read < toRead) { 218 return skipped; 219 } 220 if (charCount - skipped < toRead) { 221 toRead = (int) (charCount - skipped); 222 } 223 } 224 return skipped; 225 } 226 } 227 228 /** 229 * Reads characters and puts them into the {@code target} character buffer. 230 * 231 * @param target 232 * the destination character buffer. 233 * @return the number of characters put into {@code target} or -1 if the end 234 * of this reader has been reached before a character has been read. 235 * @throws IOException 236 * if any I/O error occurs while reading from this reader. 237 * @throws NullPointerException 238 * if {@code target} is {@code null}. 239 * @throws ReadOnlyBufferException 240 * if {@code target} is read-only. 241 */ 242 public int read(CharBuffer target) throws IOException { 243 int length = target.length(); 244 char[] buf = new char[length]; 245 length = Math.min(length, read(buf)); 246 if (length > 0) { 247 target.put(buf, 0, length); 248 } 249 return length; 250 } 251} 252