001: /*
002: * An InputStreamReader that does no character encoding translations.
003: * Copyright (C) 2001 Stephen Ostermiller
004: * http://ostermiller.org/contact.pl?regarding=Java+Utilities
005: *
006: * This program is free software; you can redistribute it and/or modify
007: * it under the terms of the GNU General Public License as published by
008: * the Free Software Foundation; either version 2 of the License, or
009: * (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * See COPYING.TXT for details.
017: */
018:
019: package com.Ostermiller.util;
020:
021: import java.io.*;
022:
023: /**
024: * A StraightStreamReader is a bridge from byte streams to character streams: It reads bytes
025: * and translates them into characters without using a character encoding. The characters
026: * that a StraightStreamReader returns may not be valid Unicode characters but they are
027: * guaranteed to be in the 0x00 to 0xFF range.
028: * More information about this class is available from <a target="_top" href=
029: * "http://ostermiller.org/utils/StraightStreamReader.html">ostermiller.org</a>.
030: * <P>
031: * Most of the time you want to do character encoding translation when translating bytes to
032: * characters. If you are planning on displaying the text, you should always do this and should
033: * use an InputStreamReader for the purpose. Sometimes it is useful to treat characters as bytes
034: * with some extra bits. In these cases you would want to use a StraightStreamReader.
035: * <P>
036: * For top efficiency, consider wrapping an StraightStreamReader within a BufferedReader. For example:<br>
037: * <code>BufferedReader in = new BufferedReader(new StraightStreamReader(System.in));</code>
038: *
039: * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
040: * @since ostermillerutils 1.00.00
041: */
042: public class StraightStreamReader extends Reader {
043:
044: /**
045: * The input stream from which all methods in this class read.
046: *
047: * @since ostermillerutils 1.00.00
048: */
049: private InputStream in;
050:
051: /**
052: * A byte array to be used for calls to the InputStream. This
053: * is cached as a class variable to avoid object creation and
054: * deletion each time a read is called. This buffer may be
055: * null and may not be large enough. Make sure to check i
056: * before using it.
057: *
058: * @since ostermillerutils 1.00.00
059: */
060: private byte[] buffer;
061:
062: /**
063: * Create a StraightStreamReader from an InputStream
064: *
065: * @param in InputStream to wrap a Reader around.
066: *
067: * @since ostermillerutils 1.00.00
068: */
069: public StraightStreamReader(InputStream in) {
070: this .in = in;
071: }
072:
073: /**
074: * Close the stream.
075: *
076: * @throws IOException If an I/O error occurs
077: *
078: * @since ostermillerutils 1.00.00
079: */
080: @Override
081: public void close() throws IOException {
082: in.close();
083: }
084:
085: /**
086: * Mark the present position in the stream. Subsequent calls to reset()
087: * will attempt to reposition the stream to this point. Not all
088: * character-input streams support the mark() operation.
089: *
090: * @param readAheadLimit Limit on the number of characters that may be read
091: * while still preserving the mark. After reading this many characters,
092: * attempting to reset the stream may fail.
093: * @throws IOException If the stream does not support mark(), or if some other I/O error occurs
094: *
095: * @since ostermillerutils 1.00.00
096: */
097: @Override
098: public void mark(int readAheadLimit) throws IOException {
099: in.mark(readAheadLimit);
100: }
101:
102: /**
103: * Tell whether this stream supports the mark() operation.
104: *
105: * @return true if and only if this stream supports the mark operation.
106: *
107: * @since ostermillerutils 1.00.00
108: */
109: @Override
110: public boolean markSupported() {
111: return in.markSupported();
112: }
113:
114: /**
115: * Read a single character. This method will block until a character is available, an
116: * I/O error occurs, or the end of the stream is reached.
117: *
118: * @return The character read, as an integer in the range 0 to 256 (0x00-0xff), or -1 if
119: * the end of the stream has been reached
120: * @throws IOException If an I/O error occurs
121: *
122: * @since ostermillerutils 1.00.00
123: */
124: @Override
125: public int read() throws IOException {
126: return in.read();
127: }
128:
129: /**
130: * Read characters into an array. This method will block until some input is available,
131: * an I/O error occurs, or the end of the stream is reached.
132: *
133: * @param cbuf Destination buffer
134: * @return The number of bytes read, or -1 if the end of the stream has been reached
135: * @throws IOException If an I/O error occurs
136: *
137: * @since ostermillerutils 1.00.00
138: */
139: @Override
140: public int read(char[] cbuf) throws IOException {
141: return read(cbuf, 0, cbuf.length);
142: }
143:
144: /**
145: * Read characters into an array. This method will block until some input is available,
146: * an I/O error occurs, or the end of the stream is reached.
147: *
148: * @param cbuf Destination buffer
149: * @param off Offset at which to start storing characters
150: * @param len Maximum number of characters to read
151: * @return The number of bytes read, or -1 if the end of the stream has been reached
152: * @throws IOException If an I/O error occurs
153: *
154: * @since ostermillerutils 1.00.00
155: */
156: @Override
157: public int read(char[] cbuf, int off, int len) throws IOException {
158: // ensure the capacity of the buffer that we will be using
159: // to read from the input stream
160: if (buffer == null || buffer.length < len) {
161: buffer = new byte[len];
162: }
163: // read from the input stream and copy it to the character array
164: int length = in.read(buffer, 0, len);
165: for (int i = 0; i < length; i++) {
166: cbuf[off + i] = (char) (0xFF & buffer[i]);
167: }
168: return length;
169: }
170:
171: /**
172: * Tell whether this stream is ready to be read.
173: *
174: * @return True if the next read() is guaranteed not to block for input, false otherwise.
175: * Note that returning false does not guarantee that the next read will block.
176: * @throws IOException If an I/O error occurs
177: *
178: * @since ostermillerutils 1.00.00
179: */
180: @Override
181: public boolean ready() throws IOException {
182: return (in.available() > 0);
183: }
184:
185: /**
186: * Reset the stream. If the stream has been marked, then attempt to reposition it at the mark.
187: * If the stream has not been marked, then attempt to reset it in some way appropriate to the
188: * particular stream, for example by repositioning it to its starting point. Not all
189: * character-input streams support the reset() operation, and some support reset()
190: * without supporting mark().
191: *
192: * @throws IOException If the stream has not been marked, or if the mark has been invalidated,
193: * or if the stream does not support reset(), or if some other I/O error occurs
194: *
195: * @since ostermillerutils 1.00.00
196: */
197: @Override
198: public void reset() throws IOException {
199: in.reset();
200: }
201:
202: /**
203: * Skip characters. This method will block until some characters are available,
204: * an I/O error occurs, or the end of the stream is reached.
205: *
206: * @param n The number of characters to skip
207: * @return The number of characters actually skipped
208: * @throws IllegalArgumentException If n is negative
209: * @throws IOException If an I/O error occurs
210: *
211: * @since ostermillerutils 1.00.00
212: */
213: @Override
214: public long skip(long n) throws IOException {
215: return in.skip(n);
216: }
217: }
|