blobbuffer.java

来自「jtds的源码 是你学习java的好东西」· Java 代码 · 共 1,265 行 · 第 1/3 页

JAVA
1,265
字号
        if (writePtr > length) {
            length = writePtr;
        }
    }

    /**
     * Reads in the specified page from the disk buffer.
     * <p/>
     * Any existing dirty page is first saved to disk.
     *
     * @param page the page number
     * @throws IOException if an I/O error occurs
     */
    public void readPage(int page) throws IOException {
        page = page & PAGE_MASK;
        if (bufferDirty) {
            writePage(currentPage);
        }
        if (page > raFile.length()) {
            throw new IOException("readPage: Invalid page number " + page);
        }
        currentPage = page;
        // Locate and read requested page
        // NB. Page may not be completely filled.
        raFile.seek(currentPage);
        // Repeat reading until buffer is filled or EOF is reached
        int count = 0, res;
        do {
            res = raFile.read(buffer, count, buffer.length - count);
            count += (res == -1) ? 0 : res;
        } while (count < PAGE_SIZE && res != -1);
    }

    /**
     * Writes the specified page to the disk buffer.
     *
     * @param page the page number
     * @throws IOException if an I/O error occurs
     */
    public void writePage(int page) throws IOException {
        page = page & PAGE_MASK;
        if (page > raFile.length()) {
            throw new IOException("writePage: Invalid page number " + page);
        }
        if (buffer.length != PAGE_SIZE) {
            throw new IllegalStateException("writePage: buffer size invalid");
        }
        raFile.seek(page);
        raFile.write(buffer);
        bufferDirty = false;
    }

    /**
     * Logically closes the file or physically close it if the open count is
     * now zero.
     * <p/>
     * Any updated buffer in memory is flushed to disk before the file is
     * closed.
     *
     * @throws IOException if an I/O error occurs
     */
    public void close() throws IOException {
        if (openCount > 0) {
            if (--openCount == 0 && raFile != null) {
                if (bufferDirty) {
                    writePage(currentPage);
                }
                raFile.close();
                raFile = null;
                // Allow buffer to be garbage collected
                buffer = EMPTY_BUFFER;
                currentPage = INVALID_PAGE;
            }
        }
    }

    /**
     * Increases the size of the in memory buffer for situations where disk
     * storage of BLOB is not possible.
     *
     * @param minSize the minimum size of buffer required
     */
    public void growBuffer(int minSize) {
        if (buffer.length == 0) {
            // Assign initial buffer
            buffer = new byte[Math.max(PAGE_SIZE, minSize)];
        } else {
            byte[] tmp;
            if (buffer.length * 2 > minSize && buffer.length <= MAX_BUF_INC) {
                tmp = new byte[buffer.length * 2];
            } else {
                tmp = new byte[minSize + MAX_BUF_INC];
            }
            // Copy over existing data
            System.arraycopy(buffer, 0, tmp, 0, buffer.length);
            buffer = tmp; // Assign new buffer.
        }
    }

    /**
     * Sets the initial buffer to an existing byte array.
     *
     * @param bytes the byte array containing the BLOB data
     * @param copy  true if a local copy of the data is required
     */
    public void setBuffer(byte[] bytes, boolean copy) {
        if (copy) {
            this.buffer = new byte[bytes.length];
            System.arraycopy(bytes, 0, this.buffer, 0, buffer.length);
        } else {
            this.buffer = bytes;
        }
        this.length = buffer.length;
    }

    //
    // ---- Inner classes implementing the various input/output stream classes ---
    //

    /**
     * An <code>InputStream</code> over the BLOB buffer.
     */
    private class BlobInputStream extends InputStream {
        private int readPtr;
        private boolean open;

        /**
         * Costructs an <code>InputStream</code> object over the BLOB buffer.
         *
         * @param pos  the starting position (from 0)
         * @throws IOException if an I/O error occurs
         */
        public BlobInputStream(long pos) throws IOException {
            BlobBuffer.this.open();
            open = true;
            readPtr = (int) pos;
        }

        /**
         * Ensures underlying BLOB file can be closed even if user does not
         * close this stream.
         */
        protected void finalize() throws Throwable {
            if (open) {
                try {
                    close();
                } catch (IOException e) {
                    // Ignore closing anyway
                } finally {
                    super.finalize();
                }
            }
        }

        /**
         * Returns the number of bytes available to read.
         *
         * @throws IOException if an I/O error occurs
         */
        public int available() throws IOException {
            return (int) BlobBuffer.this.getLength() - readPtr;
        }

        /**
         * Reads the next byte from the stream.
         *
         * @return the next byte as an <code>int</code> or -1 if at EOF
         * @throws IOException if an I/O error occurs
         */
        public int read() throws IOException {
            int b = BlobBuffer.this.read(readPtr);
            if (b >= 0) {
                readPtr++;
            }
            return b;
        }

        /**
         * Reads a bytes from the stream.
         *
         * @param bytes  the byte array to fill
         * @param offset the start position in the byte array
         * @param len    the number of bytes to read
         * @return the number of bytes read or -1 if at end of file
         * @throws IOException if an I/O error occurs
         */
        public int read(byte[] bytes, int offset, int len) throws IOException {
            int b = BlobBuffer.this.read(readPtr, bytes, offset, len);
            if (b > 0) {
                readPtr += b;
            }
            return b;
        }

        /**
         * Closes the output stream.
         *
         * @throws IOException if an I/O error occurs
         */
        public void close() throws IOException {
            if (open) {
                BlobBuffer.this.close();
                open = false;
            }
        }
    }

    /**
     * A Big Endian Unicode <code>InputStream</code> over the CLOB buffer.
     */
    private class UnicodeInputStream extends InputStream {
        private int readPtr;
        private boolean open;

        /**
         * Costructs an InputStream object over the BLOB buffer.
         *
         * @param pos  the starting position (from 0)
         * @throws IOException if an I/O error occurs
         */
        public UnicodeInputStream(long pos) throws IOException {
            BlobBuffer.this.open();
            open = true;
            readPtr = (int) pos;
        }

        /**
         * Ensures underlying BLOB file can be closed even if user does not
         * close this stream.
         */
        protected void finalize() throws Throwable {
            if (open) {
                try {
                    close();
                } catch (IOException e) {
                    // Ignore closing anyway
                } finally {
                    super.finalize();
                }
            }
        }

        /**
         * Returns the number of bytes available to read.
         *
         * @throws IOException if an I/O error occurs
         */
        public int available() throws IOException {
            return (int) BlobBuffer.this.getLength() - readPtr;
        }

        /**
         * Reads the next byte from the stream.
         *
         * @return the next byte as an <code>int</code> or -1 if at EOF
         * @throws IOException if an I/O error occurs
         */
        public int read() throws IOException {
            //
            // The XOR of 1 with the readPtr forces the bytes to be returned
            // in big endian order.
            //
            int b = BlobBuffer.this.read(readPtr ^ 1);
            if (b >= 0) {
                readPtr++;
            }
            return b;
        }

        /**
         * Close the output stream.
         *
         * @throws IOException if an I/O error occurs
         */
        public void close() throws IOException {
            if (open) {
                BlobBuffer.this.close();
                open = false;
            }
        }
    }

    /**
     * An ASCII <code>InputStream</code> over the CLOB buffer.
     * <p/>
     * This class interprets ASCII as anything which has a value below 0x80.
     * This is more rigid than other drivers which allow any character below
     * 0x100 to be converted to returned. The more relaxed coding is useful
     * when dealing with most single byte character sets and if this behaviour
     * is desired, comment out the line indicated in the read method.
     */
    private class AsciiInputStream extends InputStream {
        private int readPtr;
        private boolean open;

        /**
         * Costructs an InputStream object over the BLOB buffer.
         *
         * @param pos  the starting position (from 0)
         * @throws IOException if an I/O error occurs
         */
        public AsciiInputStream(long pos) throws IOException {
            BlobBuffer.this.open();
            open = true;
            readPtr = (int) pos;
        }

        /**
         * Ensures underlying BLOB file can be closed even if user does not
         * close this stream.
         */
        protected void finalize() throws Throwable {
            if (open) {
                try {
                    close();
                } catch (IOException e) {
                    // Ignore closing anyway
                } finally {
                    super.finalize();
                }
            }
        }

        /**
         * Returns the number of bytes available to read.
         *
         * @throws IOException if an I/O error occurs
         */
        public int available() throws IOException {
            return ((int) BlobBuffer.this.getLength() - readPtr) / 2;
        }

        /**
         * Read the next byte from the stream.
         *
         * @return the next byte as an <code>int</code> or -1 if at EOF
         * @throws IOException if an I/O error occurs
         */
        public int read() throws IOException {
            int b1 = BlobBuffer.this.read(readPtr);
            if (b1 >= 0) {
                readPtr++;
                int b2 = BlobBuffer.this.read(readPtr);
                if (b2 >= 0) {
                    readPtr++;
                    if (b2 != 0
                            || b1 > 0x7F // Comment out this line for a more
                    // permissive interpretation of 'ASCII'.
                    ) {
                        b1 = '?'; // Not ASCII set to '?'
                    }
                    return b1;
                }
            }
            return -1;
        }

        /**
         * Closes the output stream.
         *
         * @throws IOException if an I/O error occurs
         */
        public void close() throws IOException {
            if (open) {
                BlobBuffer.this.close();
                open = false;
            }
        }
    }

    /**
     * Implements an <code>OutputStream</code> for BLOB data.
     */
    private class BlobOutputStream extends OutputStream {
        private int writePtr;
        private boolean open;

        /**
         * Costructs an OutputStream object over the BLOB buffer.
         *
         * @param pos  the starting position (from 0)
         * @throws IOException if an I/O error occurs
         */
        BlobOutputStream(long pos) throws IOException {
            BlobBuffer.this.open();
            open = true;
            writePtr = (int) pos;
        }

        /**
         * Ensures underlying BLOB file can be closed even if user does not
         * close this stream.
         */
        protected void finalize() throws Throwable {
            if (open) {
                try {
                    close();
                } catch (IOException e) {
                    // Ignore closing anyway
                } finally {
                    super.finalize();
                }
            }
        }

        /**
         * Write a byte to the BLOB buffer.
         *
         * @param b the byte value to write
         * @throws IOException if an I/O error occurs
         */
        public void write(int b) throws IOException {
            BlobBuffer.this.write(writePtr++, b);
        }

        /**
         * Write bytes to the BLOB buffer.
         *
         * @param bytes  the byte array value to write
         * @param offset the start position in the byte array
         * @param len    the number of bytes to write
         * @throws IOException if an I/O error occurs

⌨️ 快捷键说明

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