1 7 8 package java.io; 9 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater ; 10 11 33 public 34 class BufferedInputStream extends FilterInputStream { 35 36 private static int defaultBufferSize = 8192; 37 38 43 protected volatile byte buf[]; 44 45 51 private static final 52 AtomicReferenceFieldUpdater <BufferedInputStream , byte[]> bufUpdater = 53 AtomicReferenceFieldUpdater.newUpdater 54 (BufferedInputStream .class, byte[].class, "buf"); 55 56 65 protected int count; 66 67 82 protected int pos; 83 84 111 protected int markpos = -1; 112 113 125 protected int marklimit; 126 127 131 private InputStream getInIfOpen() throws IOException { 132 InputStream input = in; 133 if (input == null) 134 throw new IOException ("Stream closed"); 135 return input; 136 } 137 138 142 private byte[] getBufIfOpen() throws IOException { 143 byte[] buffer = buf; 144 if (buffer == null) 145 throw new IOException ("Stream closed"); 146 return buffer; 147 } 148 149 157 public BufferedInputStream(InputStream in) { 158 this(in, defaultBufferSize); 159 } 160 161 173 public BufferedInputStream(InputStream in, int size) { 174 super(in); 175 if (size <= 0) { 176 throw new IllegalArgumentException ("Buffer size <= 0"); 177 } 178 buf = new byte[size]; 179 } 180 181 188 private void fill() throws IOException { 189 byte[] buffer = getBufIfOpen(); 190 if (markpos < 0) 191 pos = 0; 192 else if (pos >= buffer.length) 193 if (markpos > 0) { 194 int sz = pos - markpos; 195 System.arraycopy(buffer, markpos, buffer, 0, sz); 196 pos = sz; 197 markpos = 0; 198 } else if (buffer.length >= marklimit) { 199 markpos = -1; 200 pos = 0; 201 } else { 202 int nsz = pos * 2; 203 if (nsz > marklimit) 204 nsz = marklimit; 205 byte nbuf[] = new byte[nsz]; 206 System.arraycopy(buffer, 0, nbuf, 0, pos); 207 if (!bufUpdater.compareAndSet(this, buffer, nbuf)) { 208 throw new IOException ("Stream closed"); 214 } 215 buffer = nbuf; 216 } 217 count = pos; 218 int n = getInIfOpen().read(buffer, pos, buffer.length - pos); 219 if (n > 0) 220 count = n + pos; 221 } 222 223 233 public synchronized int read() throws IOException { 234 if (pos >= count) { 235 fill(); 236 if (pos >= count) 237 return -1; 238 } 239 return getBufIfOpen()[pos++] & 0xff; 240 } 241 242 246 private int read1(byte[] b, int off, int len) throws IOException { 247 int avail = count - pos; 248 if (avail <= 0) { 249 253 if (len >= getBufIfOpen().length && markpos < 0) { 254 return getInIfOpen().read(b, off, len); 255 } 256 fill(); 257 avail = count - pos; 258 if (avail <= 0) return -1; 259 } 260 int cnt = (avail < len) ? avail : len; 261 System.arraycopy(getBufIfOpen(), pos, b, off, cnt); 262 pos += cnt; 263 return cnt; 264 } 265 266 301 public synchronized int read(byte b[], int off, int len) 302 throws IOException 303 { 304 getBufIfOpen(); if ((off | len | (off + len) | (b.length - (off + len))) < 0) { 306 throw new IndexOutOfBoundsException (); 307 } else if (len == 0) { 308 return 0; 309 } 310 311 int n = 0; 312 for (;;) { 313 int nread = read1(b, off + n, len - n); 314 if (nread <= 0) 315 return (n == 0) ? nread : n; 316 n += nread; 317 if (n >= len) 318 return n; 319 InputStream input = in; 321 if (input != null && input.available() <= 0) 322 return n; 323 } 324 } 325 326 334 public synchronized long skip(long n) throws IOException { 335 getBufIfOpen(); if (n <= 0) { 337 return 0; 338 } 339 long avail = count - pos; 340 341 if (avail <= 0) { 342 if (markpos <0) 344 return getInIfOpen().skip(n); 345 346 fill(); 348 avail = count - pos; 349 if (avail <= 0) 350 return 0; 351 } 352 353 long skipped = (avail < n) ? avail : n; 354 pos += skipped; 355 return skipped; 356 } 357 358 374 public synchronized int available() throws IOException { 375 return getInIfOpen().available() + (count - pos); 376 } 377 378 386 public synchronized void mark(int readlimit) { 387 marklimit = readlimit; 388 markpos = pos; 389 } 390 391 405 public synchronized void reset() throws IOException { 406 getBufIfOpen(); if (markpos < 0) 408 throw new IOException ("Resetting to invalid mark"); 409 pos = markpos; 410 } 411 412 423 public boolean markSupported() { 424 return true; 425 } 426 427 433 public void close() throws IOException { 434 byte[] buffer; 435 while ( (buffer = buf) != null) { 436 if (bufUpdater.compareAndSet(this, buffer, null)) { 437 InputStream input = in; 438 in = null; 439 if (input != null) 440 input.close(); 441 return; 442 } 443 } 445 } 446 } 447 | Popular Tags |