Mercurial Hosting > luan
annotate src/goodjava/io/BufferedInputStream.java @ 1480:1f41e5921090
input buffering
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 24 Apr 2020 14:32:20 -0600 |
parents | bd13aaeaf6d4 |
children | 97740900c820 |
rev | line source |
---|---|
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
1 /* |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
2 * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
3 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
4 */ |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
5 |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
6 package goodjava.io; |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
7 |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
8 import java.io.InputStream; |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
9 import java.io.FilterInputStream; |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
10 import java.io.IOException; |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
11 |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
12 /** |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
13 * A <code>BufferedInputStream</code> adds |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
14 * functionality to another input stream-namely, |
1480 | 15 * the ability to buffer the input. When the <code>BufferedInputStream</code> |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
16 * is created, an internal buffer array is |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
17 * created. As bytes from the stream are read |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
18 * or skipped, the internal buffer is refilled |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
19 * as necessary from the contained input stream, |
1480 | 20 * many bytes at a time. |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
21 * |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
22 * @author Arthur van Hoff |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
23 * @since JDK1.0 |
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
24 */ |
1480 | 25 public final class BufferedInputStream extends FilterInputStream { |
1479 | 26 private static int DEFAULT_BUFFER_SIZE = 8192; |
1480 | 27 private final byte buf[]; |
28 private boolean isClosed = false; | |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
29 |
1479 | 30 /** |
31 * The index one greater than the index of the last valid byte in | |
32 * the buffer. | |
33 * This value is always | |
34 * in the range <code>0</code> through <code>buf.length</code>; | |
35 * elements <code>buf[0]</code> through <code>buf[count-1] | |
36 * </code>contain buffered input data obtained | |
1480 | 37 * from the underlying input stream. |
1479 | 38 */ |
1480 | 39 private int count; |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
40 |
1479 | 41 /** |
42 * The current position in the buffer. This is the index of the next | |
43 * character to be read from the <code>buf</code> array. | |
44 * <p> | |
45 * This value is always in the range <code>0</code> | |
46 * through <code>count</code>. If it is less | |
47 * than <code>count</code>, then <code>buf[pos]</code> | |
48 * is the next byte to be supplied as input; | |
49 * if it is equal to <code>count</code>, then | |
50 * the next <code>read</code> or <code>skip</code> | |
51 * operation will require more bytes to be | |
52 * read from the contained input stream. | |
53 * | |
54 * @see java.io.BufferedInputStream#buf | |
55 */ | |
1480 | 56 private int pos; |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
57 |
1480 | 58 private void checkClosed() throws IOException { |
59 if (isClosed) | |
1479 | 60 throw new IOException("Stream closed"); |
61 } | |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
62 |
1479 | 63 /** |
64 * Creates a <code>BufferedInputStream</code> | |
65 * and saves its argument, the input stream | |
66 * <code>in</code>, for later use. An internal | |
67 * buffer array is created and stored in <code>buf</code>. | |
68 * | |
69 * @param in the underlying input stream. | |
70 */ | |
71 public BufferedInputStream(InputStream in) { | |
72 this(in, DEFAULT_BUFFER_SIZE); | |
73 } | |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
74 |
1479 | 75 /** |
76 * Creates a <code>BufferedInputStream</code> | |
77 * with the specified buffer size, | |
78 * and saves its argument, the input stream | |
79 * <code>in</code>, for later use. An internal | |
80 * buffer array of length <code>size</code> | |
81 * is created and stored in <code>buf</code>. | |
82 * | |
83 * @param in the underlying input stream. | |
84 * @param size the buffer size. | |
85 */ | |
86 public BufferedInputStream(InputStream in, int size) { | |
87 super(in); | |
88 buf = new byte[size]; | |
89 } | |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
90 |
1479 | 91 /** |
1480 | 92 * Fills the buffer with more data. |
1479 | 93 * Assumes that it is being called by a synchronized method. |
94 * This method also assumes that all data has already been read in, | |
95 * hence pos > count. | |
96 */ | |
97 private void fill() throws IOException { | |
1480 | 98 pos = 0; |
99 count = 0; | |
100 int n = super.read(buf, 0, buf.length); | |
1479 | 101 if (n > 0) |
1480 | 102 count = n; |
1479 | 103 } |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
104 |
1479 | 105 /** |
106 * See | |
107 * the general contract of the <code>read</code> | |
108 * method of <code>InputStream</code>. | |
109 * | |
110 * @return the next byte of data, or <code>-1</code> if the end of the | |
111 * stream is reached. | |
112 * @exception IOException if this input stream has been closed by | |
113 * invoking its {@link #close()} method, | |
114 * or an I/O error occurs. | |
115 * @see java.io.FilterInputStream#in | |
116 */ | |
117 public synchronized int read() throws IOException { | |
1480 | 118 checkClosed(); |
1479 | 119 if (pos >= count) { |
120 fill(); | |
121 if (pos >= count) | |
122 return -1; | |
123 } | |
1480 | 124 return buf[pos++] & 0xff; |
1479 | 125 } |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
126 |
1479 | 127 /** |
128 * Read characters into a portion of an array, reading from the underlying | |
129 * stream at most once if necessary. | |
130 */ | |
1480 | 131 public synchronized int read(byte[] b, int off, int len) throws IOException { |
132 checkClosed(); | |
1479 | 133 int avail = count - pos; |
134 if (avail <= 0) { | |
1480 | 135 /* If the requested length is at least as large as the buffer, do not bother to copy the |
1479 | 136 bytes into the local buffer. In this way buffered streams will |
137 cascade harmlessly. */ | |
1480 | 138 if (len >= buf.length) { |
139 return super.read(b, off, len); | |
1479 | 140 } |
141 fill(); | |
142 avail = count - pos; | |
143 if (avail <= 0) return -1; | |
144 } | |
145 int cnt = (avail < len) ? avail : len; | |
1480 | 146 System.arraycopy(buf, pos, b, off, cnt); |
1479 | 147 pos += cnt; |
148 return cnt; | |
149 } | |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
150 |
1479 | 151 /** |
152 * See the general contract of the <code>skip</code> | |
153 * method of <code>InputStream</code>. | |
154 * | |
155 * @exception IOException if the stream does not support seek, | |
156 * or if this input stream has been closed by | |
157 * invoking its {@link #close()} method, or an | |
158 * I/O error occurs. | |
159 */ | |
160 public synchronized long skip(long n) throws IOException { | |
1480 | 161 checkClosed(); |
1479 | 162 long avail = count - pos; |
163 if (avail <= 0) { | |
1480 | 164 return super.skip(n); |
1479 | 165 } |
166 long skipped = (avail < n) ? avail : n; | |
167 pos += skipped; | |
168 return skipped; | |
169 } | |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
170 |
1479 | 171 /** |
172 * Returns an estimate of the number of bytes that can be read (or | |
173 * skipped over) from this input stream without blocking by the next | |
174 * invocation of a method for this input stream. The next invocation might be | |
175 * the same thread or another thread. A single read or skip of this | |
176 * many bytes will not block, but may read or skip fewer bytes. | |
177 * <p> | |
178 * This method returns the sum of the number of bytes remaining to be read in | |
179 * the buffer (<code>count - pos</code>) and the result of calling the | |
180 * {@link java.io.FilterInputStream#in in}.available(). | |
181 * | |
182 * @return an estimate of the number of bytes that can be read (or skipped | |
183 * over) from this input stream without blocking. | |
184 * @exception IOException if this input stream has been closed by | |
185 * invoking its {@link #close()} method, | |
186 * or an I/O error occurs. | |
187 */ | |
188 public synchronized int available() throws IOException { | |
189 int n = count - pos; | |
1480 | 190 int avail = super.available(); |
1479 | 191 return n > (Integer.MAX_VALUE - avail) |
192 ? Integer.MAX_VALUE | |
193 : n + avail; | |
194 } | |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
195 |
1480 | 196 public void mark(int readlimit) {} |
197 | |
198 public void reset() throws IOException { | |
199 throw new IOException("mark/reset not supported"); | |
1479 | 200 } |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
201 |
1479 | 202 public boolean markSupported() { |
1480 | 203 return false; |
1479 | 204 } |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
205 |
1479 | 206 /** |
207 * Closes this input stream and releases any system resources | |
208 * associated with the stream. | |
209 * Once the stream has been closed, further read(), available(), reset(), | |
210 * or skip() invocations will throw an IOException. | |
211 * Closing a previously closed stream has no effect. | |
212 * | |
213 * @exception IOException if an I/O error occurs. | |
214 */ | |
1480 | 215 public synchronized void close() throws IOException { |
216 isClosed = true; | |
217 super.close(); | |
1479 | 218 } |
1478
37e582f2e266
clone BufferedInputStream
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff
changeset
|
219 } |