分布式文件系统的发展很快,在Oracle中,LOB(Large Object,大型对象)类型的字段现在虽然用的没有以前那么多了。但是在一些特殊的场合,需要用它保存一些数据量非常大的业务领域(如图象、档案等),还是有不少的市场。
LOB类型分为BLOB和CLOB两种:BLOB即二进制大型对象(BinaryLarge Object),适用于存贮非文本的字节流数据(如程序、图象、影音等)。而CLOB,即字符型大型对象(Character Large Object),则与字符集相关,适于存贮文本型的数据(如历史档案、大部头著作,房地产交易数据和文档的记录等)。
1、准备工作
有一个能正常访问ORACLE的应用。
创建一张测试的表:
数据库
CREATE TABLE ffm_CLOB ( ID NUMBER(3),CLOBCOL CLOB)
2、Java对Oracle的clob字段进行写入、读取、修改的源代码
package com.db;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 简单的对ORACLE中的CLOB字段写、读、修改
* @author 范芳铭
*/
public class EasyClob {
public staticvoid main(String[] args) throws Exception {
EasyClobclob = new EasyClob();
clob.clobWrite("D:/ffm83/ffm83.txt");
//clob.clobRead("D:/ffm83/clobRead.txt");
}
public voidclobWrite(String filePath) throws Exception {
Connectionconn = null;
PreparedStatementstmt = null;
ResultSet rs= null;
try {
conn = Log4JDBCTest.getConnBM();
booleandefaultCommit = conn.getAutoCommit();
/* 开启事务,设定不自动提交 */
conn.setAutoCommit(false);
/* 插入一个空的CLOB对象 */
Stringsql = "INSERT INTO ffm_CLOB VALUES (?, EMPTY_CLOB())";
stmt =conn.prepareStatement(sql);
stmt.setInt(1,1);
stmt.executeUpdate();
/* 查询此CLOB对象并锁定 */
sql ="SELECT CLOBCOL FROM ffm_CLOB WHERE ID=? FOR UPDATE";
stmt =conn.prepareStatement(sql);
stmt.setInt(1,1);
rs =stmt.executeQuery();
if(rs.next()) {
/* 取出此CLOB对象 */
oracle.sql.CLOBclob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
/* 向CLOB对象中写入数据 */
BufferedWriterout = new BufferedWriter(clob.getCharacterOutputStream());
InputStreamReaderisr = new InputStreamReader(new FileInputStream(filePath), "UTF-8");
BufferedReaderin = new BufferedReader(isr);
intc;
while((c = in.read()) != -1) {
out.write(c);
System.out.println(c);
}
in.close();
out.close();
}
/* 正式提交 */
conn.commit();
} catch(Exception ex) {
conn.rollback();
throwex;
} finally {
try {
stmt.close();
conn.close();
} catch(SQLException e) {
e.printStackTrace();
}
}
}
public voidclobRead(String outFile) throws Exception {
Connectionconn = null;
PreparedStatementstmt = null;
ResultSet rs= null;
try {
conn =Log4JDBCTest.getConnBM();
booleandefaultCommit = conn.getAutoCommit();
/* 开启事务,设定不自动提交 */
conn.setAutoCommit(false);
/* 查询CLOB对象 */
Stringsql = "SELECT * FROM ffm_CLOB WHERE ID=?";
stmt =conn.prepareStatement(sql);
stmt.setInt(1,1);
rs =stmt.executeQuery();
if(rs.next()) {
/* 获取CLOB对象 */
oracle.sql.CLOBclob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
/* 以字符形式输出 */
BufferedReaderin = new BufferedReader(
clob.getCharacterStream());
BufferedWriterout = new BufferedWriter(new FileWriter(outFile));
intc;
while((c = in.read()) != -1) {
out.write(c);
}
out.close();
in.close();
}
} catch(Exception ex) {
conn.rollback();
throwex;
} finally {
try {
stmt.close();
conn.close();
} catch(SQLException e) {
e.printStackTrace();
}
}
}
public voidclobModify(String filePath) throws Exception {
Connectionconn = null;
PreparedStatementstmt = null;
ResultSet rs= null;
try {
conn =Log4JDBCTest.getConnBM();
booleandefaultCommit = conn.getAutoCommit();
/* 开启事务,设定不自动提交 */
conn.setAutoCommit(false);
/* 查询CLOB对象并锁定 */
Stringsql = "SELECT CLOBCOL FROM ffm_CLOB WHERE ID=? FOR UPDATE";
stmt =conn.prepareStatement(sql);
stmt.setInt(1,1);
rs =stmt.executeQuery();
if(rs.next()) {
/* 获取此CLOB对象 */
oracle.sql.CLOBclob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
/* 进行覆盖式修改 */
BufferedWriterout = new BufferedWriter(
clob.getCharacterOutputStream());
InputStreamReaderisr = new InputStreamReader(new FileInputStream(filePath), "UTF-8");
BufferedReaderin = new BufferedReader(isr);
intc;
while((c = in.read()) != -1) {
out.write(c);
}
in.close();
out.close();
}
/* 提交事务 */
conn.commit();
} catch(Exception ex) {
conn.rollback();
throwex;
} finally {
try {
stmt.close();
conn.close();
} catch(SQLException e) {
e.printStackTrace();
}
}
}
}
3、Java对Oracle的clob字段的中文乱码的处理
在上面的代码中,如果我用一个新建一个普通的txt文件,这个文件中只有英文或者数字的话,那么无论怎么写,都没有乱码问题,如果文件中包含了中文等字符,非常有可能会造成乱码。(为什么说有可能呢,因为有可能恰恰碰上你的数据库的编码和文件中的编码一致)。
比如这样的一段代码,在网上很流行:
/* 取出此CLOB对象 */
oracle.sql.CLOBclob = (oracle.sql.CLOB) rs.getClob("CLOBCOL");
/*向CLOB对象中写入数据 */
BufferedWriterout = new BufferedWriter(clob.getCharacterOutputStream());
BufferedReaderin = new BufferedReader(new FileReader(filePath));
这段代码没有人为的设置读入数据的编码格式,那么一切都只能碰运气。
为了确保编码的一致性,更加为了确保数据的正常保存,推荐使用下面的方式:
读取txt文件乱码:
//BufferedReaderin = new BufferedReader(new FileReader(filePath));
解决办法:
InputStreamReaderisr = new InputStreamReader(new FileInputStream(filePath), "UTF-8");
BufferedReaderin = new BufferedReader(isr);
如果你用的也是txt文本文件在测试,那么有可能读出来的也是乱码,为什么呢?因为txt文本默认不是utf-8的编码格式。
点击文件的“另存为”,在弹出框的下面选择编码格式,有一个“utf-8”的选项,选择它,然后进行测试就可以了。