⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rewindableinputstream.java

📁 电子地图服务器,搭建自己的地图服务
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
        }

        fData[fLength++] = (byte) b;
        fOffset++;

        return b & 0xff;
    } // END read()

    /**
     * Reads up to len bytes of data from the input stream into an array of
     * bytes. In its current implementation it cannot return more bytes than
     * left in the buffer if in "non-chunked" mode
     * (<code>fMayReadChunks == false</code>). After reaching the end of
     * the buffer, each invocation of this method will read exactly 1 byte
     * then. In "chunked" mode this method <em>may</em> return more than 1
     * byte, but it doesn't buffer the result.
     *
     * <p>From the other hand, for the task of reading xml declaration, such
     * behavior may be desirable, as we probably don't need reset/rewind
     * functionality after we finished with charset deduction. It is good
     * idea to call <code>enableChunkedMode</code> after that, in order to
     * improve perfomance and lessen memoery consumption when reading the rest
     * of the data.
     *
     * @return Total number of bytes actually read or <code>-1</code> if end
     *         of stream has been reached.
     *
     * @throws IOException  when an I/O error occurs while reading data
     *
     * @throws IndexOutOfBoundsException  in case of invalid <code>off</code>,
     *                 <code>len</code> and <code>b.length</code> combination
     */
    public int read(byte[] b, int off, int len) throws IOException {
        if (null == b) {
            throw new NullPointerException("Destination byte array is null.");
        } else if (0 == len) {
            return 0;
        } else if ((b.length < off) || (b.length < (off + len)) || (0 > off) || (0 > len)) {
            throw new IndexOutOfBoundsException();
        }

        int bytesLeft = fLength - fOffset;

        /*
         * There is no more bytes in the buffer. We either reading 1 byte
         * from underlying InputStream and saving it in the buffer, or
         * getting more bytes without saving them, depending on the value
         * of `fMayReadChunks` field.
         */
        if (bytesLeft == 0) {
            if (fOffset == fEndOffset) {
                return -1;
            }

            // better get some more for the voracious reader...
            if (fMayReadChunks) {
                // Hmm, this can be buffered in theory. But in many
                // cases this would be undesirable, so let it be as it is.
                return fInputStream.read(b, off, len);
            }

            int returnedVal = read();

            if (returnedVal == -1) {
                fEndOffset = fOffset;

                return -1;
            }

            b[off] = (byte) returnedVal;

            return 1;
        }

        /*
         * In non-chunked mode we shouldn't give out more bytes then left
         * in the buffer.
         */
        if (fMayReadChunks) {
            // Count of bytes to get form buffer
            int readFromBuffer = (len < bytesLeft) ? len : bytesLeft;

            System.arraycopy(fData, fOffset, b, off, readFromBuffer);

            int readFromStream = 0;

            if (len > bytesLeft) {
                readFromStream = fInputStream.read(b, off + bytesLeft, len - bytesLeft);
            }

            fOffset += readFromBuffer;

            return readFromBuffer + ((-1 == readFromStream) ? 0 : readFromStream);
        } else {
            //
            // This will prevent returning more bytes than the remainder of
            // the buffer array.
            if (len > bytesLeft) {
                len = bytesLeft;
            }

            System.arraycopy(fData, fOffset, b, off, len);

            fOffset += len;

            return len;
        }
    } // END read(byte[], int, int)

    /**
     * Skips over and discards <code>n</code> bytes of data from this input
     * stream. The skip method may, for a variety of reasons, end up skipping
     * over some smaller number of bytes, possibly <code>0</code>. The actual
     * number of bytes skipped is returned. If <code>n</code> is negative, no
     * bytes are skipped.
     *
     * @param  n  Number of bytes to be skipped.
     *
     * @return Number of bytes actually skipped.
     *
     * @throws IOException if an I/O error occurs.
     */
    public long skip(long n) throws IOException {
        int bytesLeft;

        if (n <= 0) {
            return 0;
        }

        bytesLeft = fLength - fOffset;

        // If end of buffer is reached, using `skip()` of the underlying input
        // stream
        if (bytesLeft == 0) {
            if (fOffset == fEndOffset) {
                return 0;
            }

            return fInputStream.skip(n);
        }

        // Quickly "skipping" bytes in the buffer by modifying its pointer.
        if (n <= bytesLeft) {
            fOffset += n;

            return n;
        }

        fOffset += bytesLeft;

        if (fOffset == fEndOffset) {
            return bytesLeft;
        }

        n -= bytesLeft;

        return fInputStream.skip(n) + bytesLeft;
    } // END skip(long)

    /**
     * Returns the number of bytes that can be read (or skipped over) from this
     * input stream without blocking by the next caller of a method for this
     * input stream. For <code>RewindableInputStream</code> this can be:
     *
     * <ul>
     *   <li>
     *    Number of unread bytes in the <code>fData</code> buffer, i.e. those
     *    between current position (fOffset) and total bytes quantity in the
     *    buffer (fLength).
     *   </li>
     *   <li>
     *    Result of underlying InputStream's <code>available</code> call
     *    if there are no unread bytes in the buffer.
     *   </li>
     *   <li>
     *    <code>-1</code> if end of stream is reached.
     *   </li>
     * </ul>
     *
     * @return the number of bytes that can be read from this input stream
     *         without blocking.
     *
     * @throws IOException when an I/O error occurs.
     */
    public int available() throws IOException {
        int bytesLeft = fLength - fOffset;

        if (bytesLeft == 0) {
            // Again, the same thing as in `read()`. Do we need to throw
            // an exception if fOffset > fEndOffset???
            if (fOffset == fEndOffset) {
                return -1;
            }

            /*
             * In a manner of speaking, when this class isn't permitting more
             * than one byte at a time to be read, it is "blocking".  The
             * available() method should indicate how much can be read without
             * blocking, so while we're in this mode, it should only indicate
             * that bytes in its buffer are available; otherwise, the result of
             * available() on the underlying InputStream is appropriate.
             */
            return fMayReadChunks ? fInputStream.available() : 0;
        }

        return bytesLeft;
    }

    /**
     * Sets a mark to the current position in the stream.
     *
     * @param  howMuch  Not used in this implementation I guess.
     */
    public void mark(int howMuch) {
        fMark = fOffset;
    }

    /**
     * Returns stream pointer to the position previously remembered
     * using <code>mark</code> method (or to beginning of the stream,
     * if there were no <code>mark</code> method calls).
     */
    public void reset() {
        fOffset = fMark;
    }

    /**
     * Tells that this stream supports mark/reset capability.
     * This one definitely supports it :)
     *
     * @return <code>true</code> if this stream instance supports the mark
     *         and reset methods; <code>false</code> otherwise.
     */
    public boolean markSupported() {
        return true;
    }

    /**
     * Closes underlying byte stream.
     *
     * @throws IOException if an I/O error occurs.
     */
    public void close() throws IOException {
        if (fInputStream != null) {
            fInputStream.close();
            fInputStream = null;
            fData = null;
        }
    }
} // end of RewindableInputStream class

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -