神通数据库 JDBC DRIVER中的STREAM¶
JDBC标准中提供了三种流BinaryStream、AsciiStream和CharacterStream。另外也提供了UnicodeStream。但是标准中申明UnicodeStream已经废弃不用了。在本节中我们将只讨论BinaryStream、AsciiStream和CharacterStream。
AsciiStream和CharacterStream是对应于CHAR、VARCHAR和TEXT类型。当使用AsciiStream读取字符时,会将字符当作Ascii字符读取出来,当使用CharacterStream读取字符时,会将字符当作Unicode-16读取出来。
BinaryStream对应于BINARY和VARBINARY类型。
在ResultSet对象中提供了getAsciiStream()、getCharacterStream()和getBinaryStream()方法,通过这些方法应用程序就可以不一次将数据全部取出来。在ResultSet中,相对于getAsciiStream()和getCharacterStream()对应的方法是getString();与getBinaryStram()相对应的方法是getBytes()。下面就举一个例子,说明两者读取的区别。
在示例中,第一个示例我们先用getBytes()方法从ResultSet对象中将数据取出来, 然后将取出来的数据写到文件中去;第二个示例调用getBinaryStream()方法从ResultSet对象 中取出数据来,然后将取出来的数据同样写到文件中去。这里假设后台数据库已经有表GIFTABLE, 且它的两个字段分别为NAME,它的数据类型为VARCHAR,GIFPICTURE,它的数据类型为VARBINARY。
package com.sun.cts.tests.jdbc.help_doc.ru_men;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import org.junit.Test;
public class StreamTEST {
private Connection con;
private Statement stmt;
public String DBUSER = "";
public String DBPASSWD = "";
public String DBURL = "";
public String DBDRIVER = "";
public void init() {
Properties prop = new Properties();
try {
FileInputStream in = new FileInputStream(
"." + File.separator + "testFile" + File.separator + "cts_env.properties");
prop.load(in);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
//从配置文件读取
// DBUSER = "sysdba";
DBUSER = prop.getProperty("DBUSER");
// DBPASSWD = "szoscar55";
DBPASSWD = prop.getProperty("DBPASSWD");
// DBURL = "jdbc:oscar://localhost:2003/osrdb";
DBURL = prop.getProperty("DBURL");
// DBDRIVER = "com.oscar.Driver";
DBDRIVER = prop.getProperty("DBDRIVER");
try {
Class.forName(DBDRIVER);
con = DriverManager.getConnection(DBURL, DBUSER, DBPASSWD);
} catch (Exception e) {
e.printStackTrace();
}
}
private void creTable() {
try {
stmt = con.createStatement();
// 创建表
String sql = "CREATE TABLE GIFTABLE" + "(name varchar(10) not NULL,GIFPICTURE VARBINARY(255))";
stmt.executeUpdate(sql);
// 插入数据
byte[] byBuffer = new byte[200];
String strInput = "abcdefg";
byBuffer = strInput.getBytes();
PreparedStatement pst = con.prepareStatement("INSERT INTO GIFTABLE VALUES(?,?)");
pst.setString(1, "gif1");
pst.setBytes(2, byBuffer);
pst.execute();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void delTable() {
try {
// 删除表
String sql = "DROP TABLE GIFTABLE";
stmt.executeUpdate(sql);
stmt.close();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
private void execute1() {
try {
// 获取数据
String sql = "SELECT GIFPICTURE FROM GIFTABLE WHERE NAME='gif1'";
ResultSet rs = stmt.executeQuery(sql);
if (rs.next()) {
FileOutputStream fos = null;
byte[] bytes = rs.getBytes(1);
try {
fos = new FileOutputStream("test/bin.txt");
fos.write(bytes);
} catch (Exception e) {
String err = e.toString();
System.out.println(err);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ie) {
System.out.println(ie);
}
}
}
}
rs.close();
} catch (SQLException e1) {
fail(e1.getMessage());
}
}
private void execute2() {
ResultSet rs;
try {
rs = stmt.executeQuery("SELECT GIFPICTURE FROM GIFTABLE WHERE NAME='gif1'");
if (rs.next()) {
FileOutputStream fos = null;
byte[] bytes = new byte[1024];
InputStream is = rs.getAsciiStream(1);
try {
fos = new FileOutputStream("test/cin.txt");
int len = 0;
while ((len = is.read(bytes)) > 0){
fos.write(bytes, 0, len);
}
} catch (Exception e) {
fail(e.getMessage());
String err = e.toString();
System.out.println(err);
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException ie) {
System.out.println(ie);
}
}
try {
is.close();
} catch (IOException ie) {
System.out.println(ie);
}
}
}
rs.close();
} catch (SQLException e1) {
fail(e1.getMessage());
}
}
@Test
public void execute() {
init();
creTable();
execute1();
execute2();
delTable();
}
public static void main(String[] args) throws SQLException {
new StreamTEST().execute();
}
}
由execute1()和execute2()可以看出,execute1()中直接将数据全部取出来然后写到文件中去;而execute2()中则是开了一个缓冲区,每次读取的数据不超过缓冲区的大小,然后将读取的数据写到文件中去。这里缓冲区的大小完全由应用程序来指定,这样极大地增强了应用程序的灵活性。别忘了,在使用完流后,请将流关闭。只需简单的调用close()方法就行了。对于AsciiStream和CharacterStream同BinaryStream一样,不在这里一一列举。
讨论到流,必须要讨论另外一种特殊的可以操纵更大数据量的类型BLOB和CLOB。这两种数据类型在前面的数据类型映射中,我们可以发现它们分别对应于JAVA语言中的java.sql.Blob和java.sql.Clob。这两种数据类型,可以存放更大的数据量,理论上是没有限制的,但实际应用中却由应用程序的运行环境所决定,比如内存、硬盘等。对于这两种数据类型,JDBC提供了标准的Blob和Clob接口。Blob是用来处理二进制流,而Clob是用来处理字符流。关于这两种接口更详细的描述,我们将在大对象这一章中给出。总之,使用流可以极大地增加程序的灵活性,使程序在某些情况下更加健壮。