如何在java中读取oracle blob
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在java中读取oracle blob相关的知识,希望对你有一定的参考价值。
整个流程分为四步,连接oracle数据库 -> 读取blob图片字段 -> 对图片进行缩放 ->把图片展示在jsp页面上。下面进行详细描述:
1. java连接Oracle
注:数据库是Oracle10g版本为10.2.0, 在数据库中,图片字段类型为BLOB。
java中通常使用的是通过jdbc驱动来连接数据库,oracle也不例外,因此必须下载一个Oracle驱动的jdbc需要去网上进行下载,名称为 ojdbc14.jar。
下载地址为:
下载了驱动之后,可以使用驱动里提供的接口进行连接,具体代码如下:
import java.sql.*;
import java.io.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.AffineTransformOp;
import java.awt.geom.AffineTransform;
public class OracleQueryBean
private final String oracleDriverName = "oracle.jdbc.driver.OracleDriver";
private Connection myConnection = null;
/*图片表名*/
private String strTabName;
/*图片ID字段名*/
private String strIDName;
/*图片字段名*/
private String strImgName;
/**
* 加载java连接Oracle的jdbc驱动
*/
public OracleQueryBean()
try
Class.forName(oracleDriverName);
catch(ClassNotFoundException ex)
System.out.println("加载jdbc驱动失败,原因:" + ex.getMessage());
/**
* 获取Oracle连接对象
* @return Connection
*/
public Connection getConnection()
try
//用户名+密码; 以下使用的Test就是Oracle里的表空间
//从配置文件中读取数据库信息
GetPara oGetPara = new GetPara();
String strIP = oGetPara.getPara("serverip");
String strPort = oGetPara.getPara("port");
String strDBName = oGetPara.getPara("dbname");
String strUser = oGetPara.getPara("user");
String strPassword = oGetPara.getPara("password");
this.strTabName = oGetPara.getPara("tablename");
this.strIDName = oGetPara.getPara("imgidname");
this.strImgName = oGetPara.getPara("imgname");
String oracleUrlToConnect ="jdbc:oracle:thin:@"+strIP+":"+strPort+":"+strDBName;
this.myConnection = DriverManager.getConnection(oracleUrlToConnect, strUser, strPassword);
catch(Exception ex)
System.out.println("Can not get connection:" + ex.getMessage());
System.out.println("请检测配置文件中的数据库信息是否正确." );
return this.myConnection;
2. 读取blob字段
在OracleQueryBean类中增加一个函数,来进行读取,具体代码如下:
/**
* 根据图片在数据库中的ID进行读取
* @param strID图片字段ID
* @param w 需要缩到的宽度
* @param h 需要缩到高度
* @return
*/
public byte[] GetImgByteById(String strID, int w, int h)
//System.out.println("Get img data which id is " + nID);
if(myConnection == null)
this.getConnection();
byte[] data = null;
try
Statement stmt = myConnection.createStatement();
ResultSet myResultSet = stmt.executeQuery("select " + this.strIDName + " from " + this.strTabName + " where " + this.strIDName + "=" + strID);
StringBuffer myStringBuffer = new StringBuffer();
if (myResultSet.next())
java.sql.Blob blob = myResultSet.getBlob(this.strImgName);
InputStream inStream = blob.getBinaryStream();
try
long nLen = blob.length();
int nSize = (int) nLen;
//System.out.println("img data size is :" + nSize);
data = new byte[nSize];
inStream.read(data);
inStream.close();
catch (IOException e)
System.out.println("获取图片数据失败,原因:" + e.getMessage());
data = ChangeImgSize(data, w, h);
System.out.println(myStringBuffer.toString());
myConnection.commit();
myConnection.close();
catch (SQLException ex)
System.out.println(ex.getMessage());
return data;
3. 缩放图片
因为图片的大小可能不一致,但是在页面中输出的大小需要统一,所以需要
在OracleQueryBean类中增加一个函数,来进行缩放,具体代码如下:
/**
* 缩小或放大图片
* @param data 图片的byte数据
* @param w 需要缩到的宽度
* @param h 需要缩到高度
* @return 缩放后的图片的byte数据
*/
private byte[] ChangeImgSize(byte[] data, int nw, int nh)
byte[] newdata = null;
try
BufferedImage bis = ImageIO.read(new ByteArrayInputStream(data));
int w = bis.getWidth();
int h = bis.getHeight();
double sx = (double) nw / w;
double sy = (double) nh / h;
AffineTransform transform = new AffineTransform();
transform.setToScale(sx, sy);
AffineTransformOp ato = new AffineTransformOp(transform, null);
//原始颜色
BufferedImage bid = new BufferedImage(nw, nh, BufferedImage.TYPE_3BYTE_BGR);
ato.filter(bis, bid);
//转换成byte字节
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bid, "jpeg", baos);
newdata = baos.toByteArray();
catch(IOException e)
e.printStackTrace();
return newdata;
4. 展示在页面
页面使用OracleQueryBean来根据用户提供的图片id进行查询,在读取并进行缩放后,通过jsp页面进行展示,具体代码如下:
<%@ page language="java" contentType="text/html;;charset=gbk" %>
<jsp:useBean id="OrcleQuery" scope="page" class="HLFtiDemo.OracleQueryBean" />
<%
response.setContentType("image/jpeg");
//图片在数据库中的 ID
String strID = request.getParameter("id");
//要缩略或放大图片的宽度
String strWidth = request.getParameter("w");
//要缩略或放大图片的高度
String strHeight = request.getParameter("h");
byte[] data = null;
if(strID != null)
int nWith = Integer.parseInt(strWidth);
int nHeight = Integer.parseInt(strHeight);
//获取图片的byte数据
data = OrcleQuery.GetImgByteById(strID, nWith, nHeight);
ServletOutputStream op = response.getOutputStream();
op.write(data, 0, data.length);
op.close();
op = null;
response.flushBuffer();
//清除输出流,防止释放时被捕获异常
out.clear();
out = pageContext.pushBody();
%>
5. OracleQueryBean查询类的整体代码
OracleQueryBean.java文件代码如下所示:
import java.sql.*;
import java.io.*;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.awt.image.AffineTransformOp;
import java.awt.geom.AffineTransform;
public class OracleQueryBean
private final String oracleDriverName = "oracle.jdbc.driver.OracleDriver";
private Connection myConnection = null;
/*图片表名*/
private String strTabName;
/*图片ID字段名*/
private String strIDName;
/*图片字段名*/
private String strImgName;
/**
* 加载java连接Oracle的jdbc驱动
*/
public OracleQueryBean()
try
Class.forName(oracleDriverName);
catch(ClassNotFoundException ex)
System.out.println("加载jdbc驱动失败,原因:" + ex.getMessage());
/**
* 获取Oracle连接对象
* @return Connection
*/
public Connection getConnection()
try
//用户名+密码; 以下使用的Test就是Oracle里的表空间
//从配置文件中读取数据库信息
GetPara oGetPara = new GetPara();
这文章确实写的不错,你可以看原文 参考技术A byte[] content = null;
java.sql.Blob blob = rs.getBlob("字段名");
if (blob != null)
inStream = blob.getBinaryStream();
bot = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int len = 0;
while ((len = inStream.read(b)) != -1)
bot.write(b, 0, len);
content = bot.toByteArray();
使用 JAVA 从 Oracle 数据库中读取网络文件
【中文标题】使用 JAVA 从 Oracle 数据库中读取网络文件【英文标题】:read network file from Oracle database using JAVA 【发布时间】:2015-12-11 08:44:13 【问题描述】:我正在尝试在 Oracle 数据库中创建一个函数,该函数使用 JAVA 类从网络驱动器读取文件并将文件内容作为 BLOB 返回。
到目前为止,这是进展
JAVA 代码 - FileAPI.java
import java.lang.*;
import java.io.*;
import java.sql.*;
public class FileAPI
public static String readFile (String path, Blob[] outLob)
FileInputStream fileStream = null;
try
fileStream = new FileInputStream(path);
byte[] buffer = new byte[100];
int i = 0;
/* for testing just read 100 bytes */
/* code required for reading full file */
i = fileStream.read(buffer, 1, 100);
outLob[0] = new javax.sql.rowset.serial.SerialBlob(buffer);
if(fileStream != null)
fileStream.close();
return "success";
catch (Exception e)
return e.getMessage();
;
Oracle PL/SQL 函数
CREATE OR REPLACE FUNCTION readFile (p_path IN VARCHAR2, p_outlob IN OUT NOCOPY BLOB)
RETURN VARCHAR2
AS LANGUAGE JAVA
NAME 'FileAPI.readFile(
java.lang.String,
java.sql.Blob[]) return java.lang.String';
PL/SQL 匿名块来测试上述函数
SET SERVEROUTPUT ON;
DECLARE
l_temp BLOB;
l_res VARCHAR2(1000);
BEGIN
l_res := readFile('/mnt/servername/foldername/filename.txt',l_temp);
IF l_res = 'success'
THEN
DBMS_OUTPUT.PUT_LINE('Success, length '||dbms_lob.getlength(l_temp));
ELSE
DBMS_OUTPUT.PUT_LINE('Error info '|| l_res);
END IF;
END;
/
当我在块上方运行时,我没有收到任何错误信息。它只是打印“错误信息”。没有打印详细的异常。
有人能指出这里出了什么问题吗?
您还可以建议读取完整文件的内容并将其附加到 JAVA 中的 BLOB 变量 (outLob[0]) 中吗?
JAVA 细节
java 版本“1.7.0_79” Java(TM) SE 运行时环境 (build 1.7.0_79-b15) Java HotSpot(TM) 64 位服务器 VM(内部版本 24.79-b02,混合模式)
Oracle DB - Oracle 11g r2 EE
最好的问候,
[更新的JAVA代码]
import java.lang.*;
import java.io.*;
import java.sql.*;
public class FileAPI
public static String readFile (String path, Blob[] outLob)
FileInputStream fileStream = null;
Blob tmp = outLob[0];
try
fileStream = new FileInputStream(path);
byte[] buffer = new byte[100];
int i = 0;
/* for testing just read 100 bytes */
/* code required for reading full file */
i = fileStream.read(buffer, 0, 100);
tmp = new javax.sql.rowset.serial.SerialBlob(buffer);
outLob[0] = tmp;
if(fileStream != null)
fileStream.close();
return "success";
catch (Exception e)
//return e.getMessage();
return e.toString();
;
【问题讨论】:
尝试e.toString()
而不是e.getMessage()
。在某些情况下异常消息为空。
感谢您的回复。数组存在一些问题。我已经修好了。现在,当我运行 pl/sql 块时,出现以下错误 ORA-00932:不一致的数据类型:预期位置 2 的 OUT 参数是可转换为 Oracle 类型的用户定义 Java 类的实例,得到了一个不能被转换
在 JAVA 中 Oracle 数据类型 BLOB 的正确数据映射是什么?或者我需要更改我的 JAVA 代码吗?
【参考方案1】:
要直接从 Java 创建 Blob,您必须访问 Connection 对象并告诉数据库通过它创建一个 Blob;然后获取blob对象的输出流并写入它。
import oracle.jdbc.OracleDriver;
import oracle.sql.BLOB;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.DriverManager;
public class FileAPI
public static String readFile(String path, Blob[] outLob)
try
DriverManager.registerDriver(new OracleDriver());
Connection conn = DriverManager.getConnection("jdbc:default:connection:");
FileInputStream fileStream = null;
fileStream = new FileInputStream(path);
outLob[0] = BLOB.createTemporary(conn, true, BLOB.DURATION_SESSION);
OutputStream BlobOS = outLob[0].setBinaryStream(0);
byte[] buffer = new byte[100];
int len = fileStream.read(buffer, 0, 100);
while (len > -1)
BlobOS.write(buffer, 0, len);
len = fileStream.read(buffer, 0, 100);
BlobOS.close();
fileStream.close();
return "success";
catch (Exception e)
e.printStackTrace();
return e.toString();
您需要包含 Oracle JDBC 才能进行编译。 BLOB.createTemporary()
甚至适用于 Java 1.4.2 (oracle 10);从 1.6 开始,sql.Connection 中有 createBlob
函数,应该也是这样。
另外,这与您的问题有点无关,但请注意,您可以在数据库服务器上的udump
日志中读取 Java 存储过程的标准输出(System.out 和 System.err),所以不要犹豫使用e.printStackTrace()
- 它极大地帮助调试。
【讨论】:
非常感谢!同时,我尝试了另一种方法并且效果很好。我很快就会在这里发布【参考方案2】:JAVA代码
import java.lang.*;
import java.io.*;
import java.sql.Blob;
public class FileAPI
public static String readFile(String path, Blob[] outLob)
FileInputStream fileStream = null;
Blob tmp = outLob[0];
OutputStream ous = null;
try
ous = tmp.setBinaryStream(1);
fileStream = new FileInputStream(path);
//System.out.println("fileStream:" + fileStream);
byte[] buffer = new byte[4096];
int read = 0;
while ((read = fileStream.read(buffer)) != -1)
ous.write(buffer, 0, read);
outLob[0] = tmp;
catch (Exception e)
return e.toString();
//System.out.println(e.toString());
finally
try
if (fileStream != null) fileStream.close();
if (ous != null) ous.close();
catch (IOException e)
return "success";
Oracle 函数
CREATE OR REPLACE FUNCTION readFile (p_path IN VARCHAR2
, p_outlob IN OUT NOCOPY BLOB
)
RETURN VARCHAR2
AS LANGUAGE JAVA
NAME 'FileAPI.readFile(
java.lang.String,
java.sql.Blob[]) return java.lang.String';
用于测试的匿名块
SET SERVEROUTPUT ON;
DECLARE
l_temp BLOB;
l_res VARCHAR2(1000);
BEGIN
-- important, this is required so that LOB pointer is passed to JAVA
DBMS_LOB.CREATETEMPORARY(l_temp,TRUE);
l_res := readFile('/mnt/servername/foldername/filename.txt',l_temp);
IF l_temp IS NOT NULL
THEN
DBMS_OUTPUT.PUT_LINE('Success, length '||dbms_lob.getlength(l_temp));
ELSE
DBMS_OUTPUT.PUT_LINE('Error info '|| l_res);
END IF;
DBMS_LOB.FREETEMPORARY(l_temp);
END;
/
注意:应使用 dbms_java.grant_permission API 向 Oracle 用户授予所需的访问权限。服务器用户(运行 Oracle 的用户)应具有网络共享的读取权限。
【讨论】:
以上是关于如何在java中读取oracle blob的主要内容,如果未能解决你的问题,请参考以下文章
Oracle中存储图片的类型为BLOB类型,Java中如何将其读取并转为字符串?