📄 blobbuffer.java
字号:
BlobBuffer.this.write(writePtr, bytes, offset, len); writePtr += len; } /** * Close 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 ASCII <code>OutputStream</code> for CLOB data. */ private class AsciiOutputStream extends OutputStream { private int writePtr; private boolean open; /** * Costructs an ASCII <code>OutputStream</code> object over the BLOB * buffer. * * @param pos the starting position (from 0) * @throws IOException if an I/O error occurs */ AsciiOutputStream(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(); } } } /** * Writes 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); BlobBuffer.this.write(writePtr++, 0); } /** * Closes the output stream. * * @throws IOException if an I/O error occurs */ public void close() throws IOException { if (open) { BlobBuffer.this.close(); open = false; } } } // // ---- Support methods for CLOB/BLOB ---- // /** * Returns the BLOB data as a byte array. * * @param pos the start position in the BLOB buffer (from 1) * @param len the number of bytes to copy * @return the requested data as a <code>byte[]</code> */ public byte[] getBytes(long pos, int len) throws SQLException { pos--; if (pos < 0) { throw new SQLException(Messages.get("error.blobclob.badpos"), "HY090"); } if (pos > this.length) { throw new SQLException(Messages.get("error.blobclob.badposlen"), "HY090"); } if (len < 0) { throw new SQLException(Messages.get("error.blobclob.badlen"), "HY090"); } if (pos + len > this.length) { // Don't throw an exception, just return as much data as available len = (int) (this.length - pos); } try { // Should not do this. It could cause trouble.// if (pos == 0 && len == buffer.length && blobFile == null) {// // There is no file and we do not need a subset of the data.// // We should copy the buffer as the user may modify its// // contents but this would be wasteful in most cases.// return buffer;// } // We do need a subset or we are reading from the file byte[] data = new byte[len]; if (blobFile == null) { // Just copy subset from memory buffer System.arraycopy(buffer, (int) (pos), data, 0, len); } else { // Copy data from disk buffer InputStream is = new BlobInputStream(pos); int bc = is.read(data); is.close(); if (bc != data.length) { throw new IOException("Unexpected EOF on BLOB data file bc=" + bc + " data.len=" + data.length); } } return data; } catch (IOException e) { throw new SQLException(Messages.get("error.generic.ioerror", e.getMessage()), "HY000"); } } /** * Retrieve the BLOB data as an <code>InputStream</code>. * * @param ascii true if an ASCII input stream should be returned * @return the <code>InputStream</code> built over the BLOB data * @throws SQLException if an error occurs */ public InputStream getBinaryStream(boolean ascii) throws SQLException { try { if (ascii) { return new AsciiInputStream(0); } else { return new BlobInputStream(0); } } catch (IOException e) { throw new SQLException(Messages.get("error.generic.ioerror", e.getMessage()), "HY000"); } } /** * Retrieve the BLOB data as an Big Endian Unicode * <code>InputStream</code>. * * @return the <code>InputStream</code> built over the BLOB data * @throws SQLException if an error occurs */ public InputStream getUnicodeStream() throws SQLException { try { return new UnicodeInputStream(0); } catch (IOException e) { throw new SQLException(Messages.get("error.generic.ioerror", e.getMessage()), "HY000"); } } /** * Creates an <code>OutputStream</code> that can be used to update the * BLOB. * <p/> * Given that we cannot know the final size of a BLOB created by the caller * of this method, we assume the worst and create a disk BLOB by default. * * @param pos the start position in the buffer (from 1) * @param ascii true if an ASCII output stream is required * @return the <code>OutputStream</code> to be used to update the BLOB * @throws SQLException if an error occurs */ public OutputStream setBinaryStream(long pos, boolean ascii) throws SQLException { pos--; if (pos < 0) { throw new SQLException(Messages.get("error.blobclob.badpos"), "HY090"); } if (pos > this.length) { throw new SQLException(Messages.get("error.blobclob.badposlen"), "HY090"); } try { if (!isMemOnly && blobFile == null) { createBlobFile(); } if (ascii) { return new AsciiOutputStream(pos); } else { return new BlobOutputStream(pos); } } catch (IOException e) { throw new SQLException(Messages.get("error.generic.ioerror", e.getMessage()), "HY000"); } } /** * Sets the content of the BLOB to the supplied byte array value. * <p/> * If the following conditions are met: * <ol> * <li>The start position is 1 * <li>The existing BLOB length is smaller or the same as the length of * the new data * <li>The new data length does not exceed the in memory limit * </ol> * then the new data is buffered entirely in memory, otherwise a disk file * is created. * * @param pos the start position in the buffer (from 1) * @param bytes the byte array containing the data to copy * @param offset the start position in the byte array (from 0) * @param len the number of bytes to copy * @param copy true if a local copy of the byte array is required * @return the number of bytes copied * @throws SQLException if an error occurs */ public int setBytes(long pos, byte[] bytes, int offset, int len, boolean copy) throws SQLException { pos--; if (pos < 0) { throw new SQLException(Messages.get("error.blobclob.badpos"), "HY090"); } if (pos > this.length) { throw new SQLException(Messages.get("error.blobclob.badposlen"), "HY090"); } if (bytes == null) { throw new SQLException(Messages.get("error.blob.bytesnull"), "HY009"); } if (offset < 0 || offset > bytes.length) { throw new SQLException(Messages.get("error.blobclob.badoffset"), "HY090"); } if (len < 0 || pos + len > (long) Integer.MAX_VALUE || offset + len > bytes.length) { throw new SQLException(Messages.get("error.blobclob.badlen"), "HY090"); } // // If there is no disk file and this data will replace the // existing contents of the BLOB then just copy byte data to // a new buffer array if the size is small enough. // if (blobFile == null && pos == 0 && len >= this.length && len <= maxMemSize) { if (copy) { buffer = new byte[len]; System.arraycopy(bytes, offset, buffer, 0, len); } else { // A copy is not always required buffer = bytes; } length = len; return len; } try { // // OK we will now try and create a BLOB file as this // is a more complex update. // if (!isMemOnly && blobFile == null) { createBlobFile(); } // // Open the BLOB file // open(); int ptr = (int) pos; write(ptr, bytes, offset, len); close(); return len; } catch (IOException e) { throw new SQLException(Messages.get("error.generic.ioerror", e.getMessage()), "HY000"); } } /** * Retrieves the length of this BLOB buffer in bytes. * * @return the length of the BLOB data in bytes */ public long getLength() { return this.length; } /** * Retrieves the length of the BLOB buffer (in memory version only). * * @param length the length of the valid data in the buffer */ public void setLength(long length) { this.length = (int) length; } /** * Truncates the BLOB buffer to the specified size. * * @param len the required length * @throws SQLException if an error occurs */ public void truncate(long len) throws SQLException { if (len < 0) { throw new SQLException(Messages.get("error.blobclob.badlen"), "HY090"); } if (len > this.length) { throw new SQLException(Messages.get("error.blobclob.lentoolong"), "HY090"); } length = (int) len; if (len == 0) { try { // Try to discard and delete work file // Any open input streams will get EOF // open write streams will probably fail. if (blobFile != null) { if (raFile != null) { raFile.close(); } blobFile.delete(); } } catch (IOException e) { throw new SQLException(Messages.get("error.generic.ioerror", e.getMessage()), "HY000"); } finally { buffer = EMPTY_BUFFER; blobFile = null; raFile = null; openCount = 0; currentPage = INVALID_PAGE; } } } /** * Provides support for pattern searching methods. * * @param pattern the byte array containg the search pattern * @param start the start position in the BLOB (from 1) * @return the <code>int</code> start index for the pattern (from 1) or -1 * if the pattern is not found. * @throws SQLException if an error occurs */ public int position(byte[] pattern, long start) throws SQLException { try { start--; if (start < 0) { throw new SQLException(Messages.get("error.blobclob.badpos"), "HY090"); } if (start >= this.length) { throw new SQLException(Messages.get("error.blobclob.badposlen"), "HY090"); } if (pattern == null) { throw new SQLException(Messages.get("error.blob.badpattern"), "HY009"); } if (pattern.length == 0 || length == 0 || pattern.length > length) { // Impossible for there to be a match return -1; } // FIXME Implement a better (O(n)) search algorithm int limit = (int) length - pattern.length; if (blobFile == null) { for (int i = (int) start; i <= limit; i++) { int p; for (p = 0; p < pattern.length && buffer[i + p] == pattern[p]; p++); if (p == pattern.length) { return i + 1; } } } else { open(); for (int i = (int) start; i <= limit; i++) { int p; for (p = 0; p < pattern.length && read(i + p) == (pattern[p] & 0xFF); p++); if (p == pattern.length) { close(); return i + 1; } } close(); } return -1; } catch (IOException e) { throw new SQLException(Messages.get("error.generic.ioerror", e.getMessage()), "HY000"); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -