📄 blobbuffer.java
字号:
/** * 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 */ public void write(byte[] bytes, int offset, int len) throws IOException {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -