KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > imageio > stream > ImageInputStreamImpl


1 /*
2  * @(#)ImageInputStreamImpl.java 1.53 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.imageio.stream;
9
10 import java.io.DataInput JavaDoc;
11 import java.io.DataInputStream JavaDoc;
12 import java.io.EOFException JavaDoc;
13 import java.io.File JavaDoc;
14 import java.io.FileNotFoundException JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.RandomAccessFile JavaDoc;
17 import java.nio.ByteOrder JavaDoc;
18 import java.util.Stack JavaDoc;
19 import javax.imageio.IIOException JavaDoc;
20
21 /**
22  * An abstract class implementing the <code>ImageInputStream</code> interface.
23  * This class is designed to reduce the number of methods that must
24  * be implemented by subclasses.
25  *
26  * <p> In particular, this class handles most or all of the details of
27  * byte order interpretation, buffering, mark/reset, discarding,
28  * closing, and disposing.
29  */

30 public abstract class ImageInputStreamImpl implements ImageInputStream JavaDoc {
31
32     private Stack JavaDoc markByteStack = new Stack JavaDoc();
33
34     private Stack JavaDoc markBitStack = new Stack JavaDoc();
35
36     private boolean isClosed = false;
37
38     // Length of the buffer used for readFully(type[], int, int)
39
private static final int BYTE_BUF_LENGTH = 8192;
40
41     // Byte buffer used for readFully(type[], int, int)
42
private byte[] byteBuf = new byte[BYTE_BUF_LENGTH];
43
44     /**
45      * The byte order of the stream as an instance of the enumeration
46      * class <code>java.nio.ByteOrder</code>, where
47      * <code>ByteOrder.BIG_ENDIAN</code> indicates network byte order
48      * and <code>ByteOrder.LITTLE_ENDIAN</code> indicates the reverse
49      * order. By default, the value is
50      * <code>ByteOrder.BIG_ENDIAN</code>.
51      */

52     protected ByteOrder JavaDoc byteOrder = ByteOrder.BIG_ENDIAN;
53
54     /**
55      * The current read position within the stream. Subclasses are
56      * responsible for keeping this value current from any method they
57      * override that alters the read position.
58      */

59     protected long streamPos;
60
61     /**
62      * The current bit offset within the stream. Subclasses are
63      * responsible for keeping this value current from any method they
64      * override that alters the bit offset.
65      */

66     protected int bitOffset;
67
68     /**
69      * The position prior to which data may be discarded. Seeking
70      * to a smaller position is not allowed. <code>flushedPos</code>
71      * will always be >= 0.
72      */

73     protected long flushedPos = 0;
74
75     /**
76      * Constructs an <code>ImageInputStreamImpl</code>.
77      */

78     public ImageInputStreamImpl() {
79     }
80
81     /**
82      * Throws an <code>IOException</code> if the stream has been closed.
83      * Subclasses may call this method from any of their methods that
84      * require the stream not to be closed.
85      *
86      * @exception IOException if the stream is closed.
87      */

88     protected final void checkClosed() throws IOException JavaDoc {
89         if (isClosed) {
90             throw new IOException JavaDoc("closed");
91         }
92     }
93
94     public void setByteOrder(ByteOrder JavaDoc byteOrder) {
95         this.byteOrder = byteOrder;
96     }
97
98     public ByteOrder JavaDoc getByteOrder() {
99         return byteOrder;
100     }
101
102     /*
103      * Reads a single byte from the stream and returns it as an
104      * <code>int</code> between 0 and 255. If EOF is reached,
105      * <code>-1</code> is returned.
106      *
107      * <p> Subclasses must provide an implementation for this method.
108      * The subclass implementation should update the stream position
109      * before exiting.
110      *
111      * <p> The bit offset within the stream must be reset to zero before
112      * the read occurs.
113      *
114      * @return the value of the next byte in the stream, or <code>-1</code>
115      * if EOF is reached.
116      *
117      * @exception IOException if the stream has been closed.
118      */

119     public abstract int read() throws IOException JavaDoc;
120
121     /**
122      * A convenience method that calls <code>read(b, 0, b.length)</code>.
123      *
124      * <p> The bit offset within the stream is reset to zero before
125      * the read occurs.
126      *
127      * @return the number of bytes actually read, or <code>-1</code>
128      * to indicate EOF.
129      *
130      * @exception NullPointerException if <code>b</code> is
131      * <code>null</code>.
132      * @exception IOException if an I/O error occurs.
133      */

134     public int read(byte[] b) throws IOException JavaDoc {
135         return read(b, 0, b.length);
136     }
137
138     /**
139      * Reads up to <code>len</code> bytes from the stream, and stores
140      * them into <code>b</code> starting at index <code>off</code>.
141      * If no bytes can be read because the end of the stream has been
142      * reached, <code>-1</code> is returned.
143      *
144      * <p> The bit offset within the stream must be reset to zero before
145      * the read occurs.
146      *
147      * <p> Subclasses must provide an implementation for this method.
148      * The subclass implementation should update the stream position
149      * before exiting.
150      *
151      * @param b an array of bytes to be written to.
152      * @param off the starting position within <code>b</code> to write to.
153      * @param len the maximum number of bytes to read.
154      *
155      * @return the number of bytes actually read, or <code>-1</code>
156      * to indicate EOF.
157      *
158      * @exception IndexOutOfBoundsException if <code>off</code> is
159      * negative, <code>len</code> is negative, or <code>off +
160      * len</code> is greater than <code>b.length</code>.
161      * @exception NullPointerException if <code>b</code> is
162      * <code>null</code>.
163      * @exception IOException if an I/O error occurs.
164      */

165     public abstract int read(byte[] b, int off, int len) throws IOException JavaDoc;
166
167     public void readBytes(IIOByteBuffer JavaDoc buf, int len) throws IOException JavaDoc {
168         if (len < 0) {
169             throw new IndexOutOfBoundsException JavaDoc("len < 0!");
170         }
171         if (buf == null) {
172             throw new NullPointerException JavaDoc("buf == null!");
173         }
174
175         byte[] data = new byte[len];
176         len = read(data, 0, len);
177         
178         buf.setData(data);
179         buf.setOffset(0);
180         buf.setLength(len);
181     }
182
183     public boolean readBoolean() throws IOException JavaDoc {
184     int ch = this.read();
185     if (ch < 0) {
186         throw new EOFException JavaDoc();
187         }
188     return (ch != 0);
189     }
190
191     public byte readByte() throws IOException JavaDoc {
192     int ch = this.read();
193     if (ch < 0) {
194         throw new EOFException JavaDoc();
195         }
196     return (byte)ch;
197     }
198
199     public int readUnsignedByte() throws IOException JavaDoc {
200         int ch = this.read();
201         if (ch < 0) {
202             throw new EOFException JavaDoc();
203         }
204         return ch;
205     }
206
207     public short readShort() throws IOException JavaDoc {
208     int ch1 = this.read();
209     int ch2 = this.read();
210     if ((ch1 | ch2) < 0) {
211         throw new EOFException JavaDoc();
212         }
213
214         if (byteOrder == ByteOrder.BIG_ENDIAN) {
215             return (short)((ch1 << 8) + (ch2 << 0));
216         } else {
217             return (short)((ch2 << 8) + (ch1 << 0));
218         }
219     }
220
221     public int readUnsignedShort() throws IOException JavaDoc {
222         return ((int)readShort()) & 0xffff;
223     }
224
225     public char readChar() throws IOException JavaDoc {
226         return (char)readShort();
227     }
228
229     public int readInt() throws IOException JavaDoc {
230     int ch1 = this.read();
231     int ch2 = this.read();
232     int ch3 = this.read();
233     int ch4 = this.read();
234     if ((ch1 | ch2 | ch3 | ch4) < 0) {
235         throw new EOFException JavaDoc();
236         }
237
238         if (byteOrder == ByteOrder.BIG_ENDIAN) {
239             return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
240         } else {
241             return ((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0));
242         }
243     }
244
245     public long readUnsignedInt() throws IOException JavaDoc {
246         return ((long)readInt()) & 0xffffffffL;
247     }
248
249     public long readLong() throws IOException JavaDoc {
250         int i1 = readInt();
251         int i2 = readInt();
252
253         if (byteOrder == ByteOrder.BIG_ENDIAN) {
254             return ((long)i1 << 32) + (i2 & 0xFFFFFFFFL);
255         } else {
256             return ((long)i2 << 32) + (i1 & 0xFFFFFFFFL);
257         }
258     }
259
260     public float readFloat() throws IOException JavaDoc {
261         return Float.intBitsToFloat(readInt());
262     }
263
264     public double readDouble() throws IOException JavaDoc {
265     return Double.longBitsToDouble(readLong());
266     }
267
268     public String JavaDoc readLine() throws IOException JavaDoc {
269     StringBuffer JavaDoc input = new StringBuffer JavaDoc();
270     int c = -1;
271     boolean eol = false;
272
273     while (!eol) {
274         switch (c = read()) {
275         case -1:
276         case '\n':
277         eol = true;
278         break;
279         case '\r':
280         eol = true;
281         long cur = getStreamPosition();
282         if ((read()) != '\n') {
283             seek(cur);
284         }
285         break;
286         default:
287         input.append((char)c);
288         break;
289         }
290     }
291
292     if ((c == -1) && (input.length() == 0)) {
293         return null;
294     }
295     return input.toString();
296     }
297
298     public String JavaDoc readUTF() throws IOException JavaDoc {
299         this.bitOffset = 0;
300         
301         // Fix 4494369: method ImageInputStreamImpl.readUTF()
302
// does not work as specified (it should always assume
303
// network byte order).
304
ByteOrder JavaDoc oldByteOrder = getByteOrder();
305         setByteOrder(ByteOrder.BIG_ENDIAN);
306
307         String JavaDoc ret;
308         try {
309             ret = DataInputStream.readUTF(this);
310         } catch (IOException JavaDoc e) {
311             // Restore the old byte order even if an exception occurs
312
setByteOrder(oldByteOrder);
313             throw e;
314         }
315
316         setByteOrder(oldByteOrder);
317     return ret;
318     }
319
320     public void readFully(byte[] b, int off, int len) throws IOException JavaDoc {
321         // Fix 4430357 - if off + len < 0, overflow occurred
322
if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
323             throw new IndexOutOfBoundsException JavaDoc
324                 ("off < 0 || len < 0 || off + len > b.length!");
325         }
326
327         while (len > 0) {
328             int nbytes = read(b, off, len);
329             if (nbytes == -1) {
330                 throw new EOFException JavaDoc();
331             }
332             off += nbytes;
333             len -= nbytes;
334         }
335     }
336
337     public void readFully(byte[] b) throws IOException JavaDoc {
338         readFully(b, 0, b.length);
339     }
340
341     public void readFully(short[] s, int off, int len) throws IOException JavaDoc {
342         // Fix 4430357 - if off + len < 0, overflow occurred
343
if (off < 0 || len < 0 || off + len > s.length || off + len < 0) {
344             throw new IndexOutOfBoundsException JavaDoc
345                 ("off < 0 || len < 0 || off + len > s.length!");
346         }
347
348         while (len > 0) {
349             int nelts = Math.min(len, byteBuf.length/2);
350             readFully(byteBuf, 0, nelts*2);
351             toShorts(byteBuf, s, off, nelts);
352             off += nelts;
353             len -= nelts;
354         }
355     }
356
357     public void readFully(char[] c, int off, int len) throws IOException JavaDoc {
358         // Fix 4430357 - if off + len < 0, overflow occurred
359
if (off < 0 || len < 0 || off + len > c.length || off + len < 0) {
360             throw new IndexOutOfBoundsException JavaDoc
361                 ("off < 0 || len < 0 || off + len > c.length!");
362         }
363
364         while (len > 0) {
365             int nelts = Math.min(len, byteBuf.length/2);
366             readFully(byteBuf, 0, nelts*2);
367             toChars(byteBuf, c, off, nelts);
368             off += nelts;
369             len -= nelts;
370         }
371     }
372
373     public void readFully(int[] i, int off, int len) throws IOException JavaDoc {
374         // Fix 4430357 - if off + len < 0, overflow occurred
375
if (off < 0 || len < 0 || off + len > i.length || off + len < 0) {
376             throw new IndexOutOfBoundsException JavaDoc
377                 ("off < 0 || len < 0 || off + len > i.length!");
378         }
379
380         while (len > 0) {
381             int nelts = Math.min(len, byteBuf.length/4);
382             readFully(byteBuf, 0, nelts*4);
383             toInts(byteBuf, i, off, nelts);
384             off += nelts;
385             len -= nelts;
386         }
387     }
388
389     public void readFully(long[] l, int off, int len) throws IOException JavaDoc {
390         // Fix 4430357 - if off + len < 0, overflow occurred
391
if (off < 0 || len < 0 || off + len > l.length || off + len < 0) {
392             throw new IndexOutOfBoundsException JavaDoc
393                 ("off < 0 || len < 0 || off + len > l.length!");
394         }
395
396         while (len > 0) {
397             int nelts = Math.min(len, byteBuf.length/8);
398             readFully(byteBuf, 0, nelts*8);
399             toLongs(byteBuf, l, off, nelts);
400             off += nelts;
401             len -= nelts;
402         }
403     }
404
405     public void readFully(float[] f, int off, int len) throws IOException JavaDoc {
406         // Fix 4430357 - if off + len < 0, overflow occurred
407
if (off < 0 || len < 0 || off + len > f.length || off + len < 0) {
408             throw new IndexOutOfBoundsException JavaDoc
409                 ("off < 0 || len < 0 || off + len > f.length!");
410         }
411
412         while (len > 0) {
413             int nelts = Math.min(len, byteBuf.length/4);
414             readFully(byteBuf, 0, nelts*4);
415             toFloats(byteBuf, f, off, nelts);
416             off += nelts;
417             len -= nelts;
418         }
419     }
420
421     public void readFully(double[] d, int off, int len) throws IOException JavaDoc {
422         // Fix 4430357 - if off + len < 0, overflow occurred
423
if (off < 0 || len < 0 || off + len > d.length || off + len < 0) {
424             throw new IndexOutOfBoundsException JavaDoc
425                 ("off < 0 || len < 0 || off + len > d.length!");
426         }
427
428         while (len > 0) {
429             int nelts = Math.min(len, byteBuf.length/8);
430             readFully(byteBuf, 0, nelts*8);
431             toDoubles(byteBuf, d, off, nelts);
432             off += nelts;
433             len -= nelts;
434         }
435     }
436
437     private void toShorts(byte[] b, short[] s, int off, int len) {
438         int boff = 0;
439         if (byteOrder == ByteOrder.BIG_ENDIAN) {
440             for (int j = 0; j < len; j++) {
441                 int b0 = b[boff];
442                 int b1 = b[boff + 1] & 0xff;
443                 s[off + j] = (short)((b0 << 8) | b1);
444                 boff += 2;
445             }
446         } else {
447             for (int j = 0; j < len; j++) {
448                 int b0 = b[boff + 1];
449                 int b1 = b[boff] & 0xff;
450                 s[off + j] = (short)((b0 << 8) | b1);
451                 boff += 2;
452             }
453         }
454     }
455
456     private void toChars(byte[] b, char[] c, int off, int len) {
457         int boff = 0;
458         if (byteOrder == ByteOrder.BIG_ENDIAN) {
459             for (int j = 0; j < len; j++) {
460                 int b0 = b[boff];
461                 int b1 = b[boff + 1] & 0xff;
462                 c[off + j] = (char)((b0 << 8) | b1);
463                 boff += 2;
464             }
465         } else {
466             for (int j = 0; j < len; j++) {
467                 int b0 = b[boff + 1];
468                 int b1 = b[boff] & 0xff;
469                 c[off + j] = (char)((b0 << 8) | b1);
470                 boff += 2;
471             }
472         }
473     }
474
475     private void toInts(byte[] b, int[] i, int off, int len) {
476         int boff = 0;
477         if (byteOrder == ByteOrder.BIG_ENDIAN) {
478             for (int j = 0; j < len; j++) {
479                 int b0 = b[boff];
480                 int b1 = b[boff + 1] & 0xff;
481                 int b2 = b[boff + 2] & 0xff;
482                 int b3 = b[boff + 3] & 0xff;
483                 i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
484                 boff += 4;
485             }
486         } else {
487             for (int j = 0; j < len; j++) {
488                 int b0 = b[boff + 3];
489                 int b1 = b[boff + 2] & 0xff;
490                 int b2 = b[boff + 1] & 0xff;
491                 int b3 = b[boff] & 0xff;
492                 i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
493                 boff += 4;
494             }
495         }
496     }
497
498     private void toLongs(byte[] b, long[] l, int off, int len) {
499         int boff = 0;
500         if (byteOrder == ByteOrder.BIG_ENDIAN) {
501             for (int j = 0; j < len; j++) {
502                 int b0 = b[boff];
503                 int b1 = b[boff + 1] & 0xff;
504                 int b2 = b[boff + 2] & 0xff;
505                 int b3 = b[boff + 3] & 0xff;
506                 int b4 = b[boff + 4];
507                 int b5 = b[boff + 5] & 0xff;
508                 int b6 = b[boff + 6] & 0xff;
509                 int b7 = b[boff + 7] & 0xff;
510                 
511                 int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
512                 int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
513                 
514                 l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);
515                 boff += 8;
516             }
517         } else {
518             for (int j = 0; j < len; j++) {
519                 int b0 = b[boff + 7];
520                 int b1 = b[boff + 6] & 0xff;
521                 int b2 = b[boff + 5] & 0xff;
522                 int b3 = b[boff + 4] & 0xff;
523                 int b4 = b[boff + 3];
524                 int b5 = b[boff + 2] & 0xff;
525                 int b6 = b[boff + 1] & 0xff;
526                 int b7 = b[boff] & 0xff;
527                 
528                 int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
529                 int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
530                 
531                 l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);
532                 boff += 8;
533             }
534         }
535     }
536
537     private void toFloats(byte[] b, float[] f, int off, int len) {
538         int boff = 0;
539         if (byteOrder == ByteOrder.BIG_ENDIAN) {
540             for (int j = 0; j < len; j++) {
541                 int b0 = b[boff];
542                 int b1 = b[boff + 1] & 0xff;
543                 int b2 = b[boff + 2] & 0xff;
544                 int b3 = b[boff + 3] & 0xff;
545                 int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
546                 f[off + j] = Float.intBitsToFloat(i);
547                 boff += 4;
548             }
549         } else {
550             for (int j = 0; j < len; j++) {
551                 int b0 = b[boff + 3];
552                 int b1 = b[boff + 2] & 0xff;
553                 int b2 = b[boff + 1] & 0xff;
554                 int b3 = b[boff + 0] & 0xff;
555                 int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
556                 f[off + j] = Float.intBitsToFloat(i);
557                 boff += 4;
558             }
559         }
560     }
561
562     private void toDoubles(byte[] b, double[] d, int off, int len) {
563         int boff = 0;
564         if (byteOrder == ByteOrder.BIG_ENDIAN) {
565             for (int j = 0; j < len; j++) {
566                 int b0 = b[boff];
567                 int b1 = b[boff + 1] & 0xff;
568                 int b2 = b[boff + 2] & 0xff;
569                 int b3 = b[boff + 3] & 0xff;
570                 int b4 = b[boff + 4];
571                 int b5 = b[boff + 5] & 0xff;
572                 int b6 = b[boff + 6] & 0xff;
573                 int b7 = b[boff + 7] & 0xff;
574                 
575                 int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
576                 int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
577                 long l = ((long)i0 << 32) | (i1 & 0xffffffffL);
578
579                 d[off + j] = Double.longBitsToDouble(l);
580                 boff += 8;
581             }
582         } else {
583             for (int j = 0; j < len; j++) {
584                 int b0 = b[boff + 7];
585                 int b1 = b[boff + 6] & 0xff;
586                 int b2 = b[boff + 5] & 0xff;
587                 int b3 = b[boff + 4] & 0xff;
588                 int b4 = b[boff + 3];
589                 int b5 = b[boff + 2] & 0xff;
590                 int b6 = b[boff + 1] & 0xff;
591                 int b7 = b[boff] & 0xff;
592                 
593                 int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
594                 int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
595                 long l = ((long)i0 << 32) | (i1 & 0xffffffffL);
596
597                 d[off + j] = Double.longBitsToDouble(l);
598                 boff += 8;
599             }
600         }
601     }
602
603     public long getStreamPosition() throws IOException JavaDoc {
604         checkClosed();
605         return streamPos;
606     }
607
608     public int getBitOffset() throws IOException JavaDoc {
609         checkClosed();
610         return bitOffset;
611     }
612
613     public void setBitOffset(int bitOffset) throws IOException JavaDoc {
614         checkClosed();
615         if (bitOffset < 0 || bitOffset > 7) {
616             throw new IllegalArgumentException JavaDoc("bitOffset must be betwwen 0 and 7!");
617         }
618         this.bitOffset = bitOffset;
619     }
620
621     public int readBit() throws IOException JavaDoc {
622         checkClosed();
623
624         // Compute final bit offset before we call read() and seek()
625
int newBitOffset = (this.bitOffset + 1) & 0x7;
626
627         int val = read();
628         if (val == -1) {
629             throw new EOFException JavaDoc();
630         }
631
632         if (newBitOffset != 0) {
633             // Move byte position back if in the middle of a byte
634
seek(getStreamPosition() - 1);
635             // Shift the bit to be read to the rightmost position
636
val >>= 8 - newBitOffset;
637         }
638         this.bitOffset = newBitOffset;
639
640         return val & 0x1;
641     }
642
643     public long readBits(int numBits) throws IOException JavaDoc {
644         checkClosed();
645
646         if (numBits < 0 || numBits > 64) {
647             throw new IllegalArgumentException JavaDoc();
648         }
649         if (numBits == 0) {
650             return 0L;
651         }
652
653         // Have to read additional bits on the left equal to the bit offset
654
int bitsToRead = numBits + bitOffset;
655
656         // Compute final bit offset before we call read() and seek()
657
int newBitOffset = (this.bitOffset + numBits) & 0x7;
658         
659         // Read a byte at a time, accumulate
660
long accum = 0L;
661         while (bitsToRead > 0) {
662             int val = read();
663             if (val == -1) {
664                 throw new EOFException JavaDoc();
665             }
666
667             accum <<= 8;
668             accum |= val;
669             bitsToRead -= 8;
670         }
671
672         // Move byte position back if in the middle of a byte
673
if (newBitOffset != 0) {
674             seek(getStreamPosition() - 1);
675         }
676         this.bitOffset = newBitOffset;
677
678         // Shift away unwanted bits on the right.
679
accum >>>= (-bitsToRead); // Negative of bitsToRead == extra bits read
680

681         // Mask out unwanted bits on the left
682
accum &= (-1L >>> (64 - numBits));
683
684         return accum;
685     }
686
687     /**
688      * Returns <code>-1L</code> to indicate that the stream has unknown
689      * length. Subclasses must override this method to provide actual
690      * length information.
691      *
692      * @return -1L to indicate unknown length.
693      */

694     public long length() {
695         return -1L;
696     }
697
698     /**
699      * Advances the current stream position by calling
700      * <code>seek(getStreamPosition() + n)</code>.
701      *
702      * <p> The bit offset is reset to zero.
703      *
704      * @param n the number of bytes to seek forward.
705      *
706      * @return an <code>int</code> representing the number of bytes
707      * skipped.
708      *
709      * @exception IOException if <code>getStreamPosition</code>
710      * throws an <code>IOException</code> when computing either
711      * the starting or ending position.
712      */

713     public int skipBytes(int n) throws IOException JavaDoc {
714         long pos = getStreamPosition();
715         seek(pos + n);
716         return (int)(getStreamPosition() - pos);
717     }
718
719     /**
720      * Advances the current stream position by calling
721      * <code>seek(getStreamPosition() + n)</code>.
722      *
723      * <p> The bit offset is reset to zero.
724      *
725      * @param n the number of bytes to seek forward.
726      *
727      * @return a <code>long</code> representing the number of bytes
728      * skipped.
729      *
730      * @exception IOException if <code>getStreamPosition</code>
731      * throws an <code>IOException</code> when computing either
732      * the starting or ending position.
733      */

734     public long skipBytes(long n) throws IOException JavaDoc {
735         long pos = getStreamPosition();
736         seek(pos + n);
737         return getStreamPosition() - pos;
738     }
739
740     public void seek(long pos) throws IOException JavaDoc {
741         checkClosed();
742
743         // This test also covers pos < 0
744
if (pos < flushedPos) {
745             throw new IndexOutOfBoundsException JavaDoc("pos < flushedPos!");
746         }
747
748         this.streamPos = pos;
749         this.bitOffset = 0;
750     }
751
752     /**
753      * Pushes the current stream position onto a stack of marked
754      * positions.
755      */

756     public void mark() {
757         try {
758             markByteStack.push(new Long JavaDoc(getStreamPosition()));
759             markBitStack.push(new Integer JavaDoc(getBitOffset()));
760         } catch (IOException JavaDoc e) {
761         }
762     }
763
764     /**
765      * Resets the current stream byte and bit positions from the stack
766      * of marked positions.
767      *
768      * <p> An <code>IOException</code> will be thrown if the previous
769      * marked position lies in the discarded portion of the stream.
770      *
771      * @exception IOException if an I/O error occurs.
772      */

773     public void reset() throws IOException JavaDoc {
774         if (markByteStack.empty()) {
775             return;
776         }
777
778         long pos = ((Long JavaDoc)markByteStack.pop()).longValue();
779         if (pos < flushedPos) {
780             throw new IIOException JavaDoc
781                 ("Previous marked position has been discarded!");
782         }
783         seek(pos);
784
785         int offset = ((Integer JavaDoc)markBitStack.pop()).intValue();
786         setBitOffset(offset);
787     }
788
789     public void flushBefore(long pos) throws IOException JavaDoc {
790         if (pos < flushedPos) {
791             throw new IndexOutOfBoundsException JavaDoc("pos < flushedPos!");
792         }
793         if (pos > getStreamPosition()) {
794             throw new IndexOutOfBoundsException JavaDoc("pos > getStreamPosition()!");
795         }
796         // Invariant: flushedPos >= 0
797
flushedPos = pos;
798     }
799
800     public void flush() throws IOException JavaDoc {
801         flushBefore(getStreamPosition());
802     }
803
804     public long getFlushedPosition() {
805         return flushedPos;
806     }
807
808     /**
809      * Default implementation returns false. Subclasses should
810      * override this if they cache data.
811      */

812     public boolean isCached() {
813         return false;
814     }
815
816     /**
817      * Default implementation returns false. Subclasses should
818      * override this if they cache data in main memory.
819      */

820     public boolean isCachedMemory() {
821         return false;
822     }
823
824     /**
825      * Default implementation returns false. Subclasses should
826      * override this if they cache data in a temporary file.
827      */

828     public boolean isCachedFile() {
829         return false;
830     }
831
832     public void close() throws IOException JavaDoc {
833         checkClosed();
834
835         isClosed = true;
836     }
837
838     /**
839      * Finalizes this object prior to garbage collection. The
840      * <code>close</code> method is called to close any open input
841      * source. This method should not be called from application
842      * code.
843      *
844      * @exception Throwable if an error occurs during superclass
845      * finalization.
846      */

847     protected void finalize() throws Throwable JavaDoc {
848         if (!isClosed) {
849             try {
850                 close();
851             } catch (IOException JavaDoc e) {
852             }
853         }
854         super.finalize();
855     }
856 }
857
Popular Tags