FileDocCategorySizeDatePackage
ImageInputStreamImpl.javaAPI DocJava SE 6 API27247Tue Jun 10 00:26:10 BST 2008javax.imageio.stream

ImageInputStreamImpl

public abstract class ImageInputStreamImpl extends Object implements ImageInputStream
An abstract class implementing the ImageInputStream interface. This class is designed to reduce the number of methods that must be implemented by subclasses.

In particular, this class handles most or all of the details of byte order interpretation, buffering, mark/reset, discarding, closing, and disposing.

Fields Summary
private Stack
markByteStack
private Stack
markBitStack
private boolean
isClosed
private static final int
BYTE_BUF_LENGTH
byte[]
byteBuf
Byte buffer used for readFully(type[], int, int). Note that this array is also used for bulk reads in readShort(), readInt(), etc, so it should be large enough to hold a primitive value (i.e. >= 8 bytes). Also note that this array is package protected, so that it can be used by ImageOutputStreamImpl in a similar manner.
protected ByteOrder
byteOrder
The byte order of the stream as an instance of the enumeration class java.nio.ByteOrder, where ByteOrder.BIG_ENDIAN indicates network byte order and ByteOrder.LITTLE_ENDIAN indicates the reverse order. By default, the value is ByteOrder.BIG_ENDIAN.
protected long
streamPos
The current read position within the stream. Subclasses are responsible for keeping this value current from any method they override that alters the read position.
protected int
bitOffset
The current bit offset within the stream. Subclasses are responsible for keeping this value current from any method they override that alters the bit offset.
protected long
flushedPos
The position prior to which data may be discarded. Seeking to a smaller position is not allowed. flushedPos will always be >= 0.
Constructors Summary
public ImageInputStreamImpl()
Constructs an ImageInputStreamImpl.


            
      
    
Methods Summary
protected final voidcheckClosed()
Throws an IOException if the stream has been closed. Subclasses may call this method from any of their methods that require the stream not to be closed.

exception
IOException if the stream is closed.

        if (isClosed) {
            throw new IOException("closed");
        }
    
public voidclose()

        checkClosed();

        isClosed = true;
    
protected voidfinalize()
Finalizes this object prior to garbage collection. The close method is called to close any open input source. This method should not be called from application code.

exception
Throwable if an error occurs during superclass finalization.

        if (!isClosed) {
            try {
                close();
            } catch (IOException e) {
            }
        }
        super.finalize();
    
public voidflush()

        flushBefore(getStreamPosition());
    
public voidflushBefore(long pos)

        checkClosed();
        if (pos < flushedPos) {
            throw new IndexOutOfBoundsException("pos < flushedPos!");
        }
        if (pos > getStreamPosition()) {
            throw new IndexOutOfBoundsException("pos > getStreamPosition()!");
        }
        // Invariant: flushedPos >= 0
        flushedPos = pos;
    
public intgetBitOffset()

        checkClosed();
        return bitOffset;
    
public java.nio.ByteOrdergetByteOrder()

        return byteOrder;
    
public longgetFlushedPosition()

        return flushedPos;
    
public longgetStreamPosition()

        checkClosed();
        return streamPos;
    
public booleanisCached()
Default implementation returns false. Subclasses should override this if they cache data.

        return false;
    
public booleanisCachedFile()
Default implementation returns false. Subclasses should override this if they cache data in a temporary file.

        return false;
    
public booleanisCachedMemory()
Default implementation returns false. Subclasses should override this if they cache data in main memory.

        return false;
    
public longlength()
Returns -1L to indicate that the stream has unknown length. Subclasses must override this method to provide actual length information.

return
-1L to indicate unknown length.

        return -1L;
    
public voidmark()
Pushes the current stream position onto a stack of marked positions.

        try {
            markByteStack.push(new Long(getStreamPosition()));
            markBitStack.push(new Integer(getBitOffset()));
        } catch (IOException e) {
        }
    
public abstract intread()
Reads a single byte from the stream and returns it as an int between 0 and 255. If EOF is reached, -1 is returned.

Subclasses must provide an implementation for this method. The subclass implementation should update the stream position before exiting.

The bit offset within the stream must be reset to zero before the read occurs.

return
the value of the next byte in the stream, or -1 if EOF is reached.
exception
IOException if the stream has been closed.

public intread(byte[] b)
A convenience method that calls read(b, 0, b.length).

The bit offset within the stream is reset to zero before the read occurs.

return
the number of bytes actually read, or -1 to indicate EOF.
exception
NullPointerException if b is null.
exception
IOException if an I/O error occurs.

        return read(b, 0, b.length);
    
public abstract intread(byte[] b, int off, int len)
Reads up to len bytes from the stream, and stores them into b starting at index off. If no bytes can be read because the end of the stream has been reached, -1 is returned.

The bit offset within the stream must be reset to zero before the read occurs.

Subclasses must provide an implementation for this method. The subclass implementation should update the stream position before exiting.

param
b an array of bytes to be written to.
param
off the starting position within b to write to.
param
len the maximum number of bytes to read.
return
the number of bytes actually read, or -1 to indicate EOF.
exception
IndexOutOfBoundsException if off is negative, len is negative, or off + len is greater than b.length.
exception
NullPointerException if b is null.
exception
IOException if an I/O error occurs.

public intreadBit()

        checkClosed();

        // Compute final bit offset before we call read() and seek()
        int newBitOffset = (this.bitOffset + 1) & 0x7;

        int val = read();
        if (val == -1) {
            throw new EOFException();
        }

        if (newBitOffset != 0) {
            // Move byte position back if in the middle of a byte
            seek(getStreamPosition() - 1);
            // Shift the bit to be read to the rightmost position
            val >>= 8 - newBitOffset;
        }
        this.bitOffset = newBitOffset;

        return val & 0x1;
    
public longreadBits(int numBits)

        checkClosed();

        if (numBits < 0 || numBits > 64) {
            throw new IllegalArgumentException();
        }
        if (numBits == 0) {
            return 0L;
        }

        // Have to read additional bits on the left equal to the bit offset
        int bitsToRead = numBits + bitOffset;

        // Compute final bit offset before we call read() and seek()
        int newBitOffset = (this.bitOffset + numBits) & 0x7;
        
        // Read a byte at a time, accumulate
        long accum = 0L;
        while (bitsToRead > 0) {
            int val = read();
            if (val == -1) {
                throw new EOFException();
            }

            accum <<= 8;
            accum |= val;
            bitsToRead -= 8;
        }

        // Move byte position back if in the middle of a byte
        if (newBitOffset != 0) {
            seek(getStreamPosition() - 1);
        }
        this.bitOffset = newBitOffset;

        // Shift away unwanted bits on the right.
        accum >>>= (-bitsToRead); // Negative of bitsToRead == extra bits read
        
        // Mask out unwanted bits on the left
        accum &= (-1L >>> (64 - numBits));

        return accum;
    
public booleanreadBoolean()

	int ch = this.read();
	if (ch < 0) {
	    throw new EOFException();
        }
	return (ch != 0);
    
public bytereadByte()

	int ch = this.read();
	if (ch < 0) {
	    throw new EOFException();
        }
	return (byte)ch;
    
public voidreadBytes(javax.imageio.stream.IIOByteBuffer buf, int len)

        if (len < 0) {
            throw new IndexOutOfBoundsException("len < 0!");
        }
        if (buf == null) {
            throw new NullPointerException("buf == null!");
        }

        byte[] data = new byte[len];
        len = read(data, 0, len);
        
        buf.setData(data);
        buf.setOffset(0);
        buf.setLength(len);
    
public charreadChar()

        return (char)readShort();
    
public doublereadDouble()

	return Double.longBitsToDouble(readLong());
    
public floatreadFloat()

        return Float.intBitsToFloat(readInt());
    
public voidreadFully(byte[] b, int off, int len)

        // Fix 4430357 - if off + len < 0, overflow occurred
        if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
            throw new IndexOutOfBoundsException
                ("off < 0 || len < 0 || off + len > b.length!");
        }

        while (len > 0) {
            int nbytes = read(b, off, len);
            if (nbytes == -1) {
                throw new EOFException();
            }
            off += nbytes;
            len -= nbytes;
        }
    
public voidreadFully(byte[] b)

        readFully(b, 0, b.length);
    
public voidreadFully(short[] s, int off, int len)

        // Fix 4430357 - if off + len < 0, overflow occurred
        if (off < 0 || len < 0 || off + len > s.length || off + len < 0) {
            throw new IndexOutOfBoundsException
                ("off < 0 || len < 0 || off + len > s.length!");
        }

        while (len > 0) {
            int nelts = Math.min(len, byteBuf.length/2);
            readFully(byteBuf, 0, nelts*2);
            toShorts(byteBuf, s, off, nelts);
            off += nelts;
            len -= nelts;
        }
    
public voidreadFully(char[] c, int off, int len)

        // Fix 4430357 - if off + len < 0, overflow occurred
        if (off < 0 || len < 0 || off + len > c.length || off + len < 0) {
            throw new IndexOutOfBoundsException
                ("off < 0 || len < 0 || off + len > c.length!");
        }

        while (len > 0) {
            int nelts = Math.min(len, byteBuf.length/2);
            readFully(byteBuf, 0, nelts*2);
            toChars(byteBuf, c, off, nelts);
            off += nelts;
            len -= nelts;
        }
    
public voidreadFully(int[] i, int off, int len)

        // Fix 4430357 - if off + len < 0, overflow occurred
        if (off < 0 || len < 0 || off + len > i.length || off + len < 0) {
            throw new IndexOutOfBoundsException
                ("off < 0 || len < 0 || off + len > i.length!");
        }

        while (len > 0) {
            int nelts = Math.min(len, byteBuf.length/4);
            readFully(byteBuf, 0, nelts*4);
            toInts(byteBuf, i, off, nelts);
            off += nelts;
            len -= nelts;
        }
    
public voidreadFully(long[] l, int off, int len)

        // Fix 4430357 - if off + len < 0, overflow occurred
        if (off < 0 || len < 0 || off + len > l.length || off + len < 0) {
            throw new IndexOutOfBoundsException
                ("off < 0 || len < 0 || off + len > l.length!");
        }

        while (len > 0) {
            int nelts = Math.min(len, byteBuf.length/8);
            readFully(byteBuf, 0, nelts*8);
            toLongs(byteBuf, l, off, nelts);
            off += nelts;
            len -= nelts;
        }
    
public voidreadFully(float[] f, int off, int len)

        // Fix 4430357 - if off + len < 0, overflow occurred
        if (off < 0 || len < 0 || off + len > f.length || off + len < 0) {
            throw new IndexOutOfBoundsException
                ("off < 0 || len < 0 || off + len > f.length!");
        }

        while (len > 0) {
            int nelts = Math.min(len, byteBuf.length/4);
            readFully(byteBuf, 0, nelts*4);
            toFloats(byteBuf, f, off, nelts);
            off += nelts;
            len -= nelts;
        }
    
public voidreadFully(double[] d, int off, int len)

        // Fix 4430357 - if off + len < 0, overflow occurred
        if (off < 0 || len < 0 || off + len > d.length || off + len < 0) {
            throw new IndexOutOfBoundsException
                ("off < 0 || len < 0 || off + len > d.length!");
        }

        while (len > 0) {
            int nelts = Math.min(len, byteBuf.length/8);
            readFully(byteBuf, 0, nelts*8);
            toDoubles(byteBuf, d, off, nelts);
            off += nelts;
            len -= nelts;
        }
    
public intreadInt()

        if (read(byteBuf, 0, 4) < 0) {
	    throw new EOFException();
        }

        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            return
                (((byteBuf[0] & 0xff) << 24) | ((byteBuf[1] & 0xff) << 16) |
                 ((byteBuf[2] & 0xff) <<  8) | ((byteBuf[3] & 0xff) <<  0));
        } else {
            return
                (((byteBuf[3] & 0xff) << 24) | ((byteBuf[2] & 0xff) << 16) |
                 ((byteBuf[1] & 0xff) <<  8) | ((byteBuf[0] & 0xff) <<  0));
        }
    
public java.lang.StringreadLine()

	StringBuffer input = new StringBuffer();
	int c = -1;
	boolean eol = false;

	while (!eol) {
	    switch (c = read()) {
	    case -1:
	    case '\n":
		eol = true;
		break;
	    case '\r":
		eol = true;
		long cur = getStreamPosition();
		if ((read()) != '\n") {
		    seek(cur);
		}
		break;
	    default:
		input.append((char)c);
		break;
	    }
	}

	if ((c == -1) && (input.length() == 0)) {
	    return null;
	}
	return input.toString();
    
public longreadLong()

        // REMIND: Once 6277756 is fixed, we should do a bulk read of all 8
        // bytes here as we do in readShort() and readInt() for even better
        // performance (see 6347575 for details).
        int i1 = readInt();
        int i2 = readInt();

        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            return ((long)i1 << 32) + (i2 & 0xFFFFFFFFL);
        } else {
            return ((long)i2 << 32) + (i1 & 0xFFFFFFFFL);
        }
    
public shortreadShort()

        if (read(byteBuf, 0, 2) < 0) {
	    throw new EOFException();
        }

        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            return (short)
                (((byteBuf[0] & 0xff) << 8) | ((byteBuf[1] & 0xff) << 0));
        } else {
            return (short)
                (((byteBuf[1] & 0xff) << 8) | ((byteBuf[0] & 0xff) << 0));
        }
    
public java.lang.StringreadUTF()

        this.bitOffset = 0;
        
        // Fix 4494369: method ImageInputStreamImpl.readUTF()
        // does not work as specified (it should always assume
        // network byte order).
        ByteOrder oldByteOrder = getByteOrder();
        setByteOrder(ByteOrder.BIG_ENDIAN);

        String ret;
        try {
            ret = DataInputStream.readUTF(this);
        } catch (IOException e) {
            // Restore the old byte order even if an exception occurs
            setByteOrder(oldByteOrder);
            throw e;
        }

        setByteOrder(oldByteOrder);
	return ret;
    
public intreadUnsignedByte()

        int ch = this.read();
        if (ch < 0) {
    	    throw new EOFException();
        }
        return ch;
    
public longreadUnsignedInt()

        return ((long)readInt()) & 0xffffffffL;
    
public intreadUnsignedShort()

        return ((int)readShort()) & 0xffff;
    
public voidreset()
Resets the current stream byte and bit positions from the stack of marked positions.

An IOException will be thrown if the previous marked position lies in the discarded portion of the stream.

exception
IOException if an I/O error occurs.

        if (markByteStack.empty()) {
            return;
        }

        long pos = ((Long)markByteStack.pop()).longValue();
        if (pos < flushedPos) {
            throw new IIOException
                ("Previous marked position has been discarded!");
        }
        seek(pos);

        int offset = ((Integer)markBitStack.pop()).intValue();
        setBitOffset(offset);
    
public voidseek(long pos)

        checkClosed();

        // This test also covers pos < 0
        if (pos < flushedPos) {
            throw new IndexOutOfBoundsException("pos < flushedPos!");
        }

        this.streamPos = pos;
        this.bitOffset = 0;
    
public voidsetBitOffset(int bitOffset)

        checkClosed();
        if (bitOffset < 0 || bitOffset > 7) {
            throw new IllegalArgumentException("bitOffset must be betwwen 0 and 7!");
        }
        this.bitOffset = bitOffset;
    
public voidsetByteOrder(java.nio.ByteOrder byteOrder)

        this.byteOrder = byteOrder;
    
public intskipBytes(int n)
Advances the current stream position by calling seek(getStreamPosition() + n).

The bit offset is reset to zero.

param
n the number of bytes to seek forward.
return
an int representing the number of bytes skipped.
exception
IOException if getStreamPosition throws an IOException when computing either the starting or ending position.

        long pos = getStreamPosition();
        seek(pos + n);
        return (int)(getStreamPosition() - pos);
    
public longskipBytes(long n)
Advances the current stream position by calling seek(getStreamPosition() + n).

The bit offset is reset to zero.

param
n the number of bytes to seek forward.
return
a long representing the number of bytes skipped.
exception
IOException if getStreamPosition throws an IOException when computing either the starting or ending position.

        long pos = getStreamPosition();
        seek(pos + n);
        return getStreamPosition() - pos;
    
private voidtoChars(byte[] b, char[] c, int off, int len)

        int boff = 0;
        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff];
                int b1 = b[boff + 1] & 0xff;
                c[off + j] = (char)((b0 << 8) | b1);
                boff += 2;
            }
        } else {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff + 1];
                int b1 = b[boff] & 0xff;
                c[off + j] = (char)((b0 << 8) | b1);
                boff += 2;
            }
        }
    
private voidtoDoubles(byte[] b, double[] d, int off, int len)

        int boff = 0;
        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff];
                int b1 = b[boff + 1] & 0xff;
                int b2 = b[boff + 2] & 0xff;
                int b3 = b[boff + 3] & 0xff;
                int b4 = b[boff + 4];
                int b5 = b[boff + 5] & 0xff;
                int b6 = b[boff + 6] & 0xff;
                int b7 = b[boff + 7] & 0xff;
                
                int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
                int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
                long l = ((long)i0 << 32) | (i1 & 0xffffffffL);

                d[off + j] = Double.longBitsToDouble(l);
                boff += 8;
            }
        } else {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff + 7];
                int b1 = b[boff + 6] & 0xff;
                int b2 = b[boff + 5] & 0xff;
                int b3 = b[boff + 4] & 0xff;
                int b4 = b[boff + 3];
                int b5 = b[boff + 2] & 0xff;
                int b6 = b[boff + 1] & 0xff;
                int b7 = b[boff] & 0xff;
                
                int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
                int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
                long l = ((long)i0 << 32) | (i1 & 0xffffffffL);

                d[off + j] = Double.longBitsToDouble(l);
                boff += 8;
            }
        }
    
private voidtoFloats(byte[] b, float[] f, int off, int len)

        int boff = 0;
        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff];
                int b1 = b[boff + 1] & 0xff;
                int b2 = b[boff + 2] & 0xff;
                int b3 = b[boff + 3] & 0xff;
                int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
                f[off + j] = Float.intBitsToFloat(i);
                boff += 4;
            }
        } else {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff + 3];
                int b1 = b[boff + 2] & 0xff;
                int b2 = b[boff + 1] & 0xff;
                int b3 = b[boff + 0] & 0xff;
                int i = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
                f[off + j] = Float.intBitsToFloat(i);
                boff += 4;
            }
        }
    
private voidtoInts(byte[] b, int[] i, int off, int len)

        int boff = 0;
        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff];
                int b1 = b[boff + 1] & 0xff;
                int b2 = b[boff + 2] & 0xff;
                int b3 = b[boff + 3] & 0xff;
                i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
                boff += 4;
            }
        } else {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff + 3];
                int b1 = b[boff + 2] & 0xff;
                int b2 = b[boff + 1] & 0xff;
                int b3 = b[boff] & 0xff;
                i[off + j] = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
                boff += 4;
            }
        }
    
private voidtoLongs(byte[] b, long[] l, int off, int len)

        int boff = 0;
        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff];
                int b1 = b[boff + 1] & 0xff;
                int b2 = b[boff + 2] & 0xff;
                int b3 = b[boff + 3] & 0xff;
                int b4 = b[boff + 4];
                int b5 = b[boff + 5] & 0xff;
                int b6 = b[boff + 6] & 0xff;
                int b7 = b[boff + 7] & 0xff;
                
                int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
                int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
                
                l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);
                boff += 8;
            }
        } else {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff + 7];
                int b1 = b[boff + 6] & 0xff;
                int b2 = b[boff + 5] & 0xff;
                int b3 = b[boff + 4] & 0xff;
                int b4 = b[boff + 3];
                int b5 = b[boff + 2] & 0xff;
                int b6 = b[boff + 1] & 0xff;
                int b7 = b[boff]     & 0xff;
                
                int i0 = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
                int i1 = (b4 << 24) | (b5 << 16) | (b6 << 8) | b7;
                
                l[off + j] = ((long)i0 << 32) | (i1 & 0xffffffffL);
                boff += 8;
            }
        }
    
private voidtoShorts(byte[] b, short[] s, int off, int len)

        int boff = 0;
        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff];
                int b1 = b[boff + 1] & 0xff;
                s[off + j] = (short)((b0 << 8) | b1);
                boff += 2;
            }
        } else {
            for (int j = 0; j < len; j++) {
                int b0 = b[boff + 1];
                int b1 = b[boff] & 0xff;
                s[off + j] = (short)((b0 << 8) | b1);
                boff += 2;
            }
        }