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 + -
显示快捷键?