|
21 | 21 |
|
22 | 22 | import static javaemul.internal.InternalPreconditions.checkNotNull; |
23 | 23 |
|
| 24 | +import java.util.Arrays; |
| 25 | + |
24 | 26 | /** |
25 | 27 | * A readable source of bytes. |
26 | 28 | * |
@@ -203,6 +205,69 @@ public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException |
203 | 205 | return byteCount; |
204 | 206 | } |
205 | 207 |
|
| 208 | + public byte[] readAllBytes() throws IOException { |
| 209 | + return readNBytes(0, Integer.MAX_VALUE); |
| 210 | + } |
| 211 | + |
| 212 | + public byte[] readNBytes(int len) throws IOException { |
| 213 | + return readNBytes(0, len); |
| 214 | + } |
| 215 | + |
| 216 | + public byte[] readNBytes(int off, int len) throws IOException { |
| 217 | + if (len == 0) { |
| 218 | + return new byte[0]; |
| 219 | + } |
| 220 | + skipNBytes(off); |
| 221 | + int capacity = Math.min(len, Math.max(2048, available())); |
| 222 | + byte[] buffer = new byte[capacity]; |
| 223 | + int pos = 0; |
| 224 | + while (pos <= len) { |
| 225 | + int chunk = read(buffer, pos, capacity - pos); |
| 226 | + if (chunk == 0) { |
| 227 | + break; |
| 228 | + } |
| 229 | + pos += chunk; |
| 230 | + if (pos == capacity) { |
| 231 | + capacity = Math.min(len, 2 * capacity); |
| 232 | + buffer = Arrays.copyOf(buffer, capacity); |
| 233 | + } |
| 234 | + } |
| 235 | + |
| 236 | + return pos < len ? Arrays.copyOf(buffer, pos) : buffer; |
| 237 | + } |
| 238 | + |
| 239 | + public int readNBytes(byte[] buffer, int off, int len) throws IOException { |
| 240 | + if (len == 0) { |
| 241 | + return 0; |
| 242 | + } |
| 243 | + skipNBytes(off); |
| 244 | + int pos = 0; |
| 245 | + while (pos <= len) { |
| 246 | + int chunk = read(buffer, pos, len); |
| 247 | + if (chunk == 0) { |
| 248 | + break; |
| 249 | + } |
| 250 | + pos += chunk; |
| 251 | + } |
| 252 | + |
| 253 | + return pos; |
| 254 | + } |
| 255 | + |
| 256 | + public void skipNBytes(long n) throws IOException { |
| 257 | + long skipped = 0; |
| 258 | + while (skipped < n) { |
| 259 | + long chunk = skip(n); |
| 260 | + if (chunk == 0) { |
| 261 | + if (read() >= 0) { |
| 262 | + skipped++; |
| 263 | + } else { |
| 264 | + throw new IOException("End of stream reached"); |
| 265 | + } |
| 266 | + } |
| 267 | + skipped += chunk; |
| 268 | + } |
| 269 | + } |
| 270 | + |
206 | 271 | /** |
207 | 272 | * Resets this stream to the last marked location. Throws an |
208 | 273 | * {@code IOException} if the number of bytes read since the mark has been |
@@ -256,4 +321,31 @@ public long skip(long byteCount) throws IOException { |
256 | 321 | } |
257 | 322 | return skipped; |
258 | 323 | } |
| 324 | + |
| 325 | + public void transferTo(OutputStream writer) throws IOException { |
| 326 | + byte[] buffer = new byte[2048]; |
| 327 | + int read; |
| 328 | + while ((read = read(buffer)) > 0) { |
| 329 | + writer.write(buffer, 0, read); |
| 330 | + } |
| 331 | + } |
| 332 | + |
| 333 | + public static InputStream nullInputStream() { |
| 334 | + return new InputStream() { |
| 335 | + private boolean closed; |
| 336 | + |
| 337 | + @Override |
| 338 | + public int read() throws IOException { |
| 339 | + if (closed) { |
| 340 | + throw new IOException("Already closed"); |
| 341 | + } |
| 342 | + return -1; |
| 343 | + } |
| 344 | + |
| 345 | + @Override |
| 346 | + public void close() { |
| 347 | + closed = true; |
| 348 | + } |
| 349 | + }; |
| 350 | + } |
259 | 351 | } |
0 commit comments