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