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: /**
021: * ByteArrayInputStream is used for streaming over a byte array.
022: *
023: * @see ByteArrayOutputStream
024: */
025: public class ByteArrayInputStream extends InputStream {
026: /**
027: * The <code>byte</code> array containing the bytes to stream over.
028: */
029: protected byte[] buf;
030:
031: /**
032: * The current position within the byte array.
033: */
034: protected int pos;
035:
036: /**
037: * The current mark position. Initially set to 0 or the <code>offset</code>
038: * parameter within the constructor.
039: */
040: protected int mark;
041:
042: /**
043: * The total number of bytes initially available in the byte array
044: * <code>buf</code>.
045: */
046: protected int count;
047:
048: /**
049: * Constructs a new ByteArrayInputStream on the byte array <code>buf</code>.
050: *
051: * @param buf
052: * the byte array to stream over
053: */
054: public ByteArrayInputStream(byte buf[]) {
055: this .mark = 0;
056: this .buf = buf;
057: this .count = buf.length;
058: }
059:
060: /**
061: * Constructs a new ByteArrayInputStream on the byte array <code>buf</code>
062: * with the position set to <code>offset</code> and the number of bytes
063: * available set to <code>offset</code> + <code>length</code>.
064: *
065: * @param buf
066: * the byte array to stream over
067: * @param offset
068: * the offset in <code>buf</code> to start streaming at
069: * @param length
070: * the number of bytes available to stream over.
071: */
072: public ByteArrayInputStream(byte buf[], int offset, int length) {
073: this .buf = buf;
074: pos = offset;
075: mark = offset;
076: count = offset + length > buf.length ? buf.length : offset
077: + length;
078: }
079:
080: /**
081: * Answers a int representing then number of bytes that are available before
082: * this ByteArrayInputStream will block. This method returns the number of
083: * bytes yet to be read from the underlying byte array.
084: *
085: * @return the number of bytes available before blocking.
086: */
087: @Override
088: public synchronized int available() {
089: return count - pos;
090: }
091:
092: /**
093: * Close the ByteArrayInputStream. This implementation frees up resources
094: * associated with this stream.
095: *
096: * @throws IOException
097: * If an error occurs attempting to close this InputStream.
098: */
099: @Override
100: public void close() throws IOException {
101: // Do nothing on close, this matches JDK behaviour.
102: }
103:
104: /**
105: * Set a Mark position in this ByteArrayInputStream. The parameter
106: * <code>readLimit</code> is ignored. Sending reset() will reposition the
107: * stream back to the marked position.
108: *
109: * @param readlimit
110: * ignored.
111: */
112: @Override
113: public synchronized void mark(int readlimit) {
114: mark = pos;
115: }
116:
117: /**
118: * Answers a boolean indicating whether or not this ByteArrayInputStream
119: * supports mark() and reset(). This implementation answers
120: * <code>true</code>.
121: *
122: * @return <code>true</code> indicates this stream supports mark/reset,
123: * <code>false
124: * <code> otherwise.
125: */
126: @Override
127: public boolean markSupported() {
128: return true;
129: }
130:
131: /**
132: * Reads a single byte from this ByteArrayInputStream and returns the result
133: * as an int. The low-order byte is returned or -1 of the end of stream was
134: * encountered. This implementation returns the next available byte from the
135: * target byte array.
136: *
137: * @return the byte read or -1 if end of stream.
138: */
139: @Override
140: public synchronized int read() {
141: return pos < count ? buf[pos++] & 0xFF : -1;
142: }
143:
144: /**
145: * Reads at most <code>len</code> bytes from this ByteArrayInputStream and
146: * stores them in byte array <code>b</code> starting at offset
147: * <code>off</code>. Answer the number of bytes actually read or -1 if no
148: * bytes were read and end of stream was encountered. This implementation
149: * reads bytes from the target byte array.
150: *
151: * @param b
152: * the byte array in which to store the read bytes.
153: * @param offset
154: * the offset in <code>b</code> to store the read bytes.
155: * @param length
156: * the maximum number of bytes to store in <code>b</code>.
157: * @return the number of bytes actually read or -1 if end of stream.
158: */
159: @Override
160: public synchronized int read(byte b[], int offset, int length) {
161: if (b == null) {
162: throw new NullPointerException();
163: }
164: // avoid int overflow
165: if (offset < 0 || offset > b.length || length < 0
166: || length > b.length - offset) {
167: throw new IndexOutOfBoundsException();
168: }
169: // Are there any bytes available?
170: if (this .pos >= this .count) {
171: return -1;
172: }
173: if (length == 0) {
174: return 0;
175: }
176:
177: int copylen = this .count - pos < length ? this .count - pos
178: : length;
179: System.arraycopy(buf, pos, b, offset, copylen);
180: pos += copylen;
181: return copylen;
182: }
183:
184: /**
185: * Reset this ByteArrayInputStream to the last marked location. This
186: * implementation resets the position to either the marked position, the
187: * start position supplied in the constructor or <code>0</code> if neither
188: * is provided.
189: */
190: @Override
191: public synchronized void reset() {
192: pos = mark;
193: }
194:
195: /**
196: * Skips <code>count</code> number of bytes in this InputStream.
197: * Subsequent <code>read()</code>'s will not return these bytes unless
198: * <code>reset()</code> is used. This implementation skips
199: * <code>count</code> number of bytes in the target stream.
200: *
201: * @param n
202: * the number of bytes to skip.
203: * @return the number of bytes actually skipped.
204: */
205: @Override
206: public synchronized long skip(long n) {
207: if (n <= 0) {
208: return 0;
209: }
210: int temp = pos;
211: pos = this .count - pos < n ? this .count : (int) (pos + n);
212: return pos - temp;
213: }
214: }
|