001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package java.io;
019:
020: import java.nio.CharBuffer;
021: import java.nio.ReadOnlyBufferException;
022:
023: /**
024: * Reader is an Abstract class for reading Character Streams. Subclasses of
025: * Reader must implement the methods <code>read(char[], int, int)</code> and
026: * <code>close()</code>.
027: *
028: * @see Writer
029: */
030: public abstract class Reader implements Readable, Closeable {
031: /**
032: * The object used to synchronize access to the reader.
033: */
034: protected Object lock;
035:
036: /**
037: * Constructs a new character stream Reader using <code>this</code> as the
038: * Object to synchronize critical regions around.
039: */
040: protected Reader() {
041: super ();
042: lock = this ;
043: }
044:
045: /**
046: * Constructs a new character stream Reader using <code>lock</code> as the
047: * Object to synchronize critical regions around.
048: *
049: * @param lock
050: * the <code>Object</code> to synchronize critical regions
051: * around.
052: */
053: protected Reader(Object lock) {
054: if (lock == null) {
055: throw new NullPointerException();
056: }
057: this .lock = lock;
058: }
059:
060: /**
061: * Close this Reader. This must be implemented by any concrete subclasses.
062: * The implementation should free any resources associated with the Reader.
063: *
064: * @throws IOException
065: * If an error occurs attempting to close this Reader.
066: */
067: public abstract void close() throws IOException;
068:
069: /**
070: * Set a Mark position in this Reader. The parameter <code>readLimit</code>
071: * indicates how many characters can be read before a mark is invalidated.
072: * Sending reset() will reposition the reader back to the marked position
073: * provided <code>readLimit</code> has not been surpassed.
074: * <p>
075: * This default implementation simply throws IOException and concrete
076: * subclasses must provide their own implementations.
077: *
078: * @param readLimit
079: * an int representing how many characters must be read before
080: * invalidating the mark.
081: *
082: * @throws IOException
083: * If an error occurs attempting mark this Reader.
084: */
085: public void mark(int readLimit) throws IOException {
086: throw new IOException();
087: }
088:
089: /**
090: * Answers a boolean indicating whether or not this Reader supports mark()
091: * and reset(). This class a default implementation which answers false.
092: *
093: * @return <code>true</code> if mark() and reset() are supported,
094: * <code>false</code> otherwise. This implementation returns
095: * <code>false</code>.
096: */
097: public boolean markSupported() {
098: return false;
099: }
100:
101: /**
102: * Reads a single character from this reader and returns the result as an
103: * int. The 2 higher-order characters are set to 0. If the end of reader was
104: * encountered then return -1.
105: *
106: * @return the character read or -1 if end of reader.
107: *
108: * @throws IOException
109: * If the Reader is already closed or some other IO error
110: * occurs.
111: */
112: public int read() throws IOException {
113: synchronized (lock) {
114: char charArray[] = new char[1];
115: if (read(charArray, 0, 1) != -1) {
116: return charArray[0];
117: }
118: return -1;
119: }
120: }
121:
122: /**
123: * Reads characters from this Reader and stores them in the character array
124: * <code>buf</code> starting at offset 0. Returns the number of characters
125: * actually read or -1 if the end of reader was encountered.
126: *
127: * @param buf
128: * character array to store the read characters
129: * @return how many characters were successfully read in or else -1 if the
130: * end of the reader was detected.
131: *
132: * @throws IOException
133: * If the Reader is already closed or some other IO error
134: * occurs.
135: */
136: public int read(char buf[]) throws IOException {
137: return read(buf, 0, buf.length);
138: }
139:
140: /**
141: * Reads at most <code>count</code> characters from this Reader and stores
142: * them at <code>offset</code> in the character array <code>buf</code>.
143: * Returns the number of characters actually read or -1 if the end of reader
144: * was encountered.
145: *
146: * @param buf
147: * character array to store the read characters
148: * @param offset
149: * offset in buf to store the read characters
150: * @param count
151: * how many characters should be read in
152: * @return how many characters were successfully read in or else -1 if the
153: * end of the reader was detected.
154: *
155: * @throws IOException
156: * If the Reader is already closed or some other IO error
157: * occurs.
158: */
159: public abstract int read(char buf[], int offset, int count)
160: throws IOException;
161:
162: /**
163: * Answers a <code>boolean</code> indicating whether or not this Reader is
164: * ready to be read without blocking. If the result is <code>true</code>,
165: * the next <code>read()</code> will not block. If the result is
166: * <code>false</code> this Reader may or may not block when
167: * <code>read()</code> is sent.
168: *
169: * @return <code>true</code> if the receiver will not block when
170: * <code>read()</code> is called, <code>false</code> if unknown
171: * or blocking will occur.
172: *
173: * @throws IOException
174: * If the Reader is already closed or some other IO error
175: * occurs.
176: */
177: public boolean ready() throws IOException {
178: return false;
179: }
180:
181: /**
182: * Reset this Readers position to the last <code>mark()</code> location.
183: * Invocations of <code>read()/skip()</code> will occur from this new
184: * location. If this Reader was not marked, the implementation of
185: * <code>reset()</code> is implementation specific. See the comment for
186: * the specific Reader subclass for implementation details. The default
187: * action is to throw <code>IOException</code>.
188: *
189: * @throws IOException
190: * If a problem occurred or the receiver does not support
191: * <code>mark()/reset()</code>.
192: */
193: public void reset() throws IOException {
194: throw new IOException();
195: }
196:
197: /**
198: * Skips <code>count</code> number of characters in this Reader.
199: * Subsequent <code>read()</code>'s will not return these characters
200: * unless <code>reset()</code> is used. This method may perform multiple
201: * reads to read <code>count</code> characters.
202: *
203: * @param count
204: * how many characters should be passed over
205: * @return how many characters were successfully passed over
206: *
207: * @throws IOException
208: * If the Reader is closed when the call is made or if an IO
209: * error occurs during the operation.
210: */
211: public long skip(long count) throws IOException {
212: if (count < 0) {
213: throw new IllegalArgumentException();
214: }
215: synchronized (lock) {
216: long skipped = 0;
217: int toRead = count < 512 ? (int) count : 512;
218: char charsSkipped[] = new char[toRead];
219: while (skipped < count) {
220: int read = read(charsSkipped, 0, toRead);
221: if (read == -1) {
222: return skipped;
223: }
224: skipped += read;
225: if (read < toRead) {
226: return skipped;
227: }
228: if (count - skipped < toRead) {
229: toRead = (int) (count - skipped);
230: }
231: }
232: return skipped;
233: }
234: }
235:
236: /**
237: * Read chars from the Reader and then put them to the <code>target</code>
238: * CharBuffer. Only put method is called on the <code>target</code>.
239: *
240: * @param target
241: * the destination CharBuffer
242: * @return the actual number of chars put to the <code>target</code>. -1
243: * when the Reader has reached the end before the method is called.
244: * @throws IOException
245: * if any I/O error raises in the procedure
246: * @throws NullPointerException
247: * if the target CharBuffer is null
248: * @throws ReadOnlyBufferException
249: * if the target CharBuffer is readonly
250: */
251: public int read(CharBuffer target) throws IOException {
252: if (null == target) {
253: throw new NullPointerException();
254: }
255: int length = target.length();
256: char[] buf = new char[length];
257: length = Math.min(length, read(buf));
258: if (length > 0) {
259: target.put(buf, 0, length);
260: }
261: return length;
262: }
263: }
|