如何將oracle中存放的圖片(如Blob類類型的欄位)還原成一副圖片

來源:互聯網
上載者:User

在Oracle中,LOB(Large Object,大型物件)類型的欄位現在用得越來越多了。因為這種類型的欄位,容量大(最多能容納4GB的資料),且一個表中可以有多個這種類型的欄位,很靈活,適用於資料量非常大的業務領域(象、檔案等)。而LONG、LONG RAW等類型的欄位,雖然儲存容量也不小(可達2GB),但由於一個表中只能有一個這樣類型的欄位的限制,現在已很少使用了。

LOB類型分為BLOB和CLOB兩種:BLOB即二進位大型物件(Binary Large Object),適用於存貯非文本的位元組流資料(如程式、圖象、影音等)。而CLOB,即字元型大型物件(Character Large Object),則與字元集相關,適於存貯文本型的資料(如曆史檔案、大部頭著作等)。

下面以程式執行個體說明通過JDBC操縱Oracle資料庫LOB類型欄位的幾種情況。

先建立如下兩個測試用的資料庫表,Power Designer PD模型如下:

[img]http://www.csdn.net/Develop/ArticleImages/18/18955/CSDN_Dev_Image_2003-6-111028171.jpg[/img]

建表SQL語句為:

CREATE TABLE TEST_CLOB ( ID NUMBER(3), CLOBCOL CLOB)

CREATE TABLE TEST_BLOB ( ID NUMBER(3), BLOBCOL BLOB)

一、 CLOB對象的存取

1、往資料庫中插入一個新的CLOB對象

public static void clobInsert(String infile) throws Exception

{

/* 設定不自動認可 */

boolean defaultCommit = conn.getAutoCommit();

conn.setAutoCommit(false);

try {

/* 插入一個空的CLOB對象 */

stmt.executeUpdate("INSERT INTO TEST_CLOB VALUES ('111', EMPTY_CLOB())");

/* 查詢此CLOB對象並鎖定 */

ResultSet rs = stmt.executeQuery("SELECT CLOBCOL FROM TEST_CLOB WHERE ID='111' FOR UPDATE");

while (rs.next()) {

/* 取出此CLOB對象 */

oracle.sql.CLOB clob = (oracle.sql.CLOB)rs.getClob("CLOBCOL");

/* 向CLOB對象中寫入資料 */

BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());

BufferedReader in = new BufferedReader(new FileReader(infile));

int c;

while ((c=in.read())!=-1) {

out.write(c);

}

in.close();

out.close();

}

/* 正式提交 */

conn.commit();

} catch (Exception ex) {

/* 出錯復原 */

conn.rollback();

throw ex;

}

/* 恢複原提交狀態 */

conn.setAutoCommit(defaultCommit);

}

2、修改CLOB對象(是在原CLOB對象基礎上進行覆蓋式的修改)

public static void clobModify(String infile) throws Exception

{

/* 設定不自動認可 */

boolean defaultCommit = conn.getAutoCommit();

conn.setAutoCommit(false);

try {

/* 查詢CLOB對象並鎖定 */

ResultSet rs = stmt.executeQuery("SELECT CLOBCOL FROM TEST_CLOB WHERE ID='111' FOR UPDATE");

while (rs.next()) {

/* 擷取此CLOB對象 */

oracle.sql.CLOB clob = (oracle.sql.CLOB)rs.getClob("CLOBCOL");

/* 進行覆蓋式修改 */

BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());

BufferedReader in = new BufferedReader(new FileReader(infile));

int c;

while ((c=in.read())!=-1) {

out.write(c);

}

in.close();

out.close();

}

/* 正式提交 */

conn.commit();

} catch (Exception ex) {

/* 出錯復原 */

conn.rollback();

throw ex;

}

/* 恢複原提交狀態 */

conn.setAutoCommit(defaultCommit);

}

3、替換CLOB對象(將原CLOB對象清除,換成一個全新的CLOB對象)

public static void clobReplace(String infile) throws Exception

{

/* 設定不自動認可 */

boolean defaultCommit = conn.getAutoCommit();

conn.setAutoCommit(false);

try {

/* 清空原CLOB對象 */

stmt.executeUpdate("UPDATE TEST_CLOB SET CLOBCOL=EMPTY_CLOB() WHERE ID='111'");

/* 查詢CLOB對象並鎖定 */

ResultSet rs = stmt.executeQuery("SELECT CLOBCOL FROM TEST_CLOB WHERE ID='111' FOR UPDATE");

while (rs.next()) {

/* 擷取此CLOB對象 */

oracle.sql.CLOB clob = (oracle.sql.CLOB)rs.getClob("CLOBCOL");

/* 更新資料 */

BufferedWriter out = new BufferedWriter(clob.getCharacterOutputStream());

BufferedReader in = new BufferedReader(new FileReader(infile));

int c;

while ((c=in.read())!=-1) {

out.write(c);

}

in.close();

out.close();

}

/* 正式提交 */

conn.commit();

} catch (Exception ex) {

/* 出錯復原 */

conn.rollback();

throw ex;

}

/* 恢複原提交狀態 */

conn.setAutoCommit(defaultCommit);

}

4、CLOB對象讀取

public static void clobRead(String outfile) throws Exception

{

/* 設定不自動認可 */

boolean defaultCommit = conn.getAutoCommit();

conn.setAutoCommit(false);

try {

/* 查詢CLOB對象 */

ResultSet rs = stmt.executeQuery("SELECT * FROM TEST_CLOB WHERE ID='111'");

while (rs.next()) {

/* 擷取CLOB對象 */

oracle.sql.CLOB clob = (oracle.sql.CLOB)rs.getClob("CLOBCOL");

/* 以字元形式輸出 */

BufferedReader in = new BufferedReader(clob.getCharacterStream());

BufferedWriter out = new BufferedWriter(new FileWriter(outfile));

int c;

while ((c=in.read())!=-1) {

out.write(c);

}

out.close();

in.close();

}

} catch (Exception ex) {

conn.rollback();

throw ex;

}

/* 恢複原提交狀態 */

conn.setAutoCommit(defaultCommit);

}

二、 BLOB對象的存取

1、 向資料庫中插入一個新的BLOB對象

public static void blobInsert(String infile) throws Exception

{

/* 設定不自動認可 */

boolean defaultCommit = conn.getAutoCommit();

conn.setAutoCommit(false);

try {

/* 插入一個空的BLOB對象 */

stmt.executeUpdate("INSERT INTO TEST_BLOB VALUES ('222', EMPTY_BLOB())");

/* 查詢此BLOB對象並鎖定 */

ResultSet rs = stmt.executeQuery("SELECT BLOBCOL FROM TEST_BLOB WHERE ID='222' FOR UPDATE");

while (rs.next()) {

/* 取出此BLOB對象 */

oracle.sql.BLOB blob = (oracle.sql.BLOB)rs.getBlob("BLOBCOL");

/* 向BLOB對象中寫入資料 */

BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());

BufferedInputStream in = new BufferedInputStream(new FileInputStream(infile));

int c;

while ((c=in.read())!=-1) {

out.write(c);

}

in.close();

out.close();

}

/* 正式提交 */

conn.commit();

} catch (Exception ex) {

/* 出錯復原 */

conn.rollback();

throw ex;

}

/* 恢複原提交狀態 */

conn.setAutoCommit(defaultCommit);

}

2、修改BLOB對象(是在原BLOB對象基礎上進行覆蓋式的修改)

public static void blobModify(String infile) throws Exception

{

/* 設定不自動認可 */

boolean defaultCommit = conn.getAutoCommit();

conn.setAutoCommit(false);

try {

/* 查詢BLOB對象並鎖定 */

ResultSet rs = stmt.executeQuery("SELECT BLOBCOL FROM TEST_BLOB WHERE ID='222' FOR UPDATE");

while (rs.next()) {

/* 取出此BLOB對象 */

oracle.sql.BLOB blob = (oracle.sql.BLOB)rs.getBlob("BLOBCOL");

/* 向BLOB對象中寫入資料 */

BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());

BufferedInputStream in = new BufferedInputStream(new FileInputStream(infile));

int c;

while ((c=in.read())!=-1) {

out.write(c);

}

in.close();

out.close();

}

/* 正式提交 */

conn.commit();

} catch (Exception ex) {

/* 出錯復原 */

conn.rollback();

throw ex;

}

/* 恢複原提交狀態 */

conn.setAutoCommit(defaultCommit);

}

3、替換BLOB對象(將原BLOB對象清除,換成一個全新的BLOB對象)

public static void blobReplace(String infile) throws Exception

{

/* 設定不自動認可 */

boolean defaultCommit = conn.getAutoCommit();

conn.setAutoCommit(false);

try {

/* 清空原BLOB對象 */

stmt.executeUpdate("UPDATE TEST_BLOB SET BLOBCOL=EMPTY_BLOB() WHERE ID='222'");

/* 查詢此BLOB對象並鎖定 */

ResultSet rs = stmt.executeQuery("SELECT BLOBCOL FROM TEST_BLOB WHERE ID='222' FOR UPDATE");

while (rs.next()) {

/* 取出此BLOB對象 */

oracle.sql.BLOB blob = (oracle.sql.BLOB)rs.getBlob("BLOBCOL");

/* 向BLOB對象中寫入資料 */

BufferedOutputStream out = new BufferedOutputStream(blob.getBinaryOutputStream());

BufferedInputStream in = new BufferedInputStream(new FileInputStream(infile));

int c;

while ((c=in.read())!=-1) {

out.write(c);

}

in.close();

out.close();

}

/* 正式提交 */

conn.commit();

} catch (Exception ex) {

/* 出錯復原 */

conn.rollback();

throw ex;

}

/* 恢複原提交狀態 */

conn.setAutoCommit(defaultCommit);

}

4、BLOB對象讀取

public static void blobRead(String outfile) throws Exception

{

/* 設定不自動認可 */

boolean defaultCommit = conn.getAutoCommit();

conn.setAutoCommit(false);

try {

/* 查詢BLOB對象 */

ResultSet rs = stmt.executeQuery("SELECT BLOBCOL FROM TEST_BLOB WHERE ID='222'");

while (rs.next()) {

/* 取出此BLOB對象 */

oracle.sql.BLOB blob = (oracle.sql.BLOB)rs.getBlob("BLOBCOL");

/* 以二進位形式輸出 */

BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outfile));

BufferedInputStream in = new BufferedInputStream(blob.getBinaryStream());

int c;

while ((c=in.read())!=-1) {

out.write(c);

}

in.close();

out.close();

}

/* 正式提交 */

conn.commit();

} catch (Exception ex) {

/* 出錯復原 */

conn.rollback();

throw ex;

}

/* 恢複原提交狀態 */

conn.setAutoCommit(defaultCommit);

}

觀察上述程式對LOB類型欄位的存取,我們可以看出,較之其它類型欄位,有下面幾個顯著不同的特點:

一是必須取消自動認可。

存取操作開始前,必須用setAutoCommit(false)取消自動認可。其它類型欄位則無此特殊要求。這是因為存取LOB類型欄位時,通常要進行多次操作可以完成。不這樣的話,Oracle將拋出“讀取違反順序”的錯誤。

二是插入方式不同。

LOB資料不能象其它類型資料一樣直接插入(INSERT)。插入前必須先插入一個空的LOB對象,CLOB類型的Null 物件為EMPTY_CLOB(),BLOB類型的Null 物件為EMPTY_BLOB()。之後通過SELECT命令查詢得到先前插入的記錄並鎖定,繼而將Null 物件修改為所要插入的LOB對象。

三是修改方式不同。

其它類型的欄位修改時,用UPDATE … SET…命令即可。而LOB類型欄位,則只能用SELECT … FOR UPDATE命令將記錄查詢出來並鎖定,然後才能修改。且修改也有兩種改法:一是在原資料基礎上的修改(即覆蓋式修改),執行SELECT … FOR UPDATE後再改資料;二是替換(先將原資料清掉,再修改),先執行UPDATE命令將LOB欄位之值設為空白的LOB對象,然後進行第一種改法。建議使用替換的方法,以實現與其它欄位UPDATE操作後一樣的效果。

四是存取時應使用由資料庫JDBC驅動程式提供的LOB操作類。

對於Oracle資料庫,應使用oracle.sql.CLOB和oracle.sql.BLOB。不使用由資料庫JDBC驅動程式提供的LOB類時,程式運行時易於出現“抽象方法調用”的錯誤,這是因為JDBC所定義的java.sql.Clob與java.sql.Blob介面,其中的一些方法並未在資料庫廠家提供的驅動程式中真正實現。

五是存取手段與檔案操作相仿。

對於BLOB類型,應用InputStream/OutputStream類,此類不進行編碼轉換,逐個位元組存取。oracle.sql.BLOB類相應提供了getBinaryStream()和getBinaryOutputStream()兩個方法,前一個方法用於讀取Oracle的BLOB欄位,後一個方法用於將資料寫入Oracle的BLOB欄位。

對於CLOB類型,應用Reader/Writer類,此類進行編碼轉換。oracle.sql.CLOB類相應提供了getCharacterStream()和getCharacterOutputStream()兩個方法,前一個方法用於讀取Oracle的CLOB欄位,後一個方法用於將資料寫入Oracle的CLOB欄位。

需要說明的是,為了大幅提高程式執行效率,對BLOB/CLOB欄位的讀寫操作,應該使用緩衝操作類(帶Buffered首碼),即:BufferedInputStream,BufferedOutputStream,BufferedReader,BufferedWriter。常式中全部使用了緩衝操作類。

 

小結:通過JDBC操縱Oracle資料庫的LOB欄位,不外乎插入、修改、替換、讀取四種方式,掌握起來並不難。在實際操作中要注意上面所說的幾點,結合閱讀常式來源程式,使用者會很快明白LOB類型欄位的使用的,也必將領悟到這種類型欄位的妙處!

[url="http://www.ccw.com.cn/resources/AD03A50E-9B02-4DB6-81C2-F5E6AD6FBCCC/src_lob.zip"]源檔案下載[/url]

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.