Reader.java revision 4fefecee9d4a5d2a4510f516b4015607b19e8d09
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 amount} 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 * count} characters. 214 * 215 * @param count 216 * the maximum number of characters to skip. 217 * @return the number of characters actually skipped. 218 * @throws IllegalArgumentException 219 * if {@code amount < 0}. 220 * @throws IOException 221 * if this reader is closed or some other I/O error occurs. 222 * @see #mark(int) 223 * @see #markSupported() 224 * @see #reset() 225 */ 226 public long skip(long count) throws IOException { 227 if (count < 0) { 228 throw new IllegalArgumentException(); 229 } 230 synchronized (lock) { 231 long skipped = 0; 232 int toRead = count < 512 ? (int) count : 512; 233 char charsSkipped[] = new char[toRead]; 234 while (skipped < count) { 235 int read = read(charsSkipped, 0, toRead); 236 if (read == -1) { 237 return skipped; 238 } 239 skipped += read; 240 if (read < toRead) { 241 return skipped; 242 } 243 if (count - skipped < toRead) { 244 toRead = (int) (count - skipped); 245 } 246 } 247 return skipped; 248 } 249 } 250 251 /** 252 * Reads characters and puts them into the {@code target} character buffer. 253 * 254 * @param target 255 * the destination character buffer. 256 * @return the number of characters put into {@code target} or -1 if the end 257 * of this reader has been reached before a character has been read. 258 * @throws IOException 259 * if any I/O error occurs while reading from this reader. 260 * @throws NullPointerException 261 * if {@code target} is {@code null}. 262 * @throws ReadOnlyBufferException 263 * if {@code target} is read-only. 264 */ 265 public int read(CharBuffer target) throws IOException { 266 if (null == target) { 267 throw new NullPointerException(); 268 } 269 int length = target.length(); 270 char[] buf = new char[length]; 271 length = Math.min(length, read(buf)); 272 if (length > 0) { 273 target.put(buf, 0, length); 274 } 275 return length; 276 } 277} 278