package
com.jasonhuang.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Properties;
import java.util.UUID;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
/**/ /*
* 测试利用 SQL Server 的 Image 类型存储文件,并从数据库取出数据存入文件
* 数据库表:
* T1_TB_TestFile
* 字段:
* [FileUUID] [char](36) NOT NULL
* [FileContent] [image] NULL
*/
public class TestMsSqlImage ... {
// Log4j Logger
private static Logger logger = Logger.getLogger(TestMsSqlImage.class);
// 数据库JDBC常量
private static String JDBC_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static String JDBC_URL = "jdbc:sqlserver://HOME-AMD";
private static String MSSQL_DATABASE = "test1";
private static String MSSQL_USER = "sa";
private static String MSSQL_PASSWORD = "123";
// 存入数据库的文件路径
private static String INPUT_FILE = "C:/Temp/生物课件.zip";
// 从数据库取出的文件路径
private static String OUTPUT_FILE = "C:/Temp/OUT.zip";
/** *//**
* 文件 -> 数据库 -> 文件
*
* @param args
*/
public static void main(String[] args) ...{
logger.setLevel(Level.ALL);
Connection conn = null;
Statement stmt = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
FileInputStream input = null;
FileOutputStream output = null;
try ...{
// 设置数据库属性
Properties properties = new Properties();
properties.setProperty("database", MSSQL_DATABASE);
properties.setProperty("user", MSSQL_USER);
properties.setProperty("password", MSSQL_PASSWORD);
// 传统JDBC获得连接
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(JDBC_URL, properties);
stmt = conn.createStatement();
// 随机获得唯一UUID
String uuid = UUID.randomUUID().toString();
// 生成一条数据库数据
sql = "insert into T1_TB_TestFile (FileUUID) values ('" + uuid
+ "')";
stmt.executeUpdate(sql);
// 即使在insert时插入image类型的值为null,数据库依然不会创建指针。可以使用update创建指针。
sql = "update T1_TB_TestFile set FileContent = null where FileUUID = '"
+ uuid + "'";
stmt.executeUpdate(sql);
// 创建缓冲区,微软建议最佳长度为8040的倍数
int length = 8040 * 100;
byte[] buffer = new byte[length];
// Image 类型的指针
byte[] ptr = null;
// 偏移量
int offset = 0;
// 读写字节数
int len = 0;
// 文件长度
long size = 0;
File file = null;
// 取消 Auto Commit
conn.setAutoCommit(false);
// 获得 Image 类型的指针
sql = "select textptr(FileContent) from T1_TB_TestFile where FileUUID = '"
+ uuid + "'";
rs = stmt.executeQuery(sql);
if (rs.next()) ...{
ptr = rs.getBytes(1);
}
rs.close();
rs = null;
if (ptr != null) ...{
// 获得文件输入流
file = new File(INPUT_FILE);
logger.info("磁盘上原始的文件长度为: " + file.length());
input = new FileInputStream(file);
// 更新 Image 类型字段,0表示不删除内容
sql = "updatetext T1_TB_TestFile.FileContent ? ? 0 ?";
pstmt = conn.prepareStatement(sql);
// 读取input流,-1表示已经读完
while ((len = input.read(buffer)) != -1) ...{
// Image 类型的指针
pstmt.setBytes(1, ptr);
// 偏移量
pstmt.setInt(2, offset);
// 写入的内容
pstmt.setBytes(3, buffer);
// 将读取内容写入数据库
pstmt.executeUpdate();
// 清空参数
pstmt.clearParameters();
// 移动偏移量
offset += len;
}
pstmt.close();
pstmt = null;
// 关闭输入流
input.close();
input = null;
// 删除多余内容,NULL 表示删除偏移量后所有内容
sql = "updatetext T1_TB_TestFile.FileContent ? ? NULL";
pstmt = conn.prepareStatement(sql);
pstmt.setBytes(1, ptr);
pstmt.setInt(2, offset);
pstmt.executeUpdate();
pstmt.close();
pstmt = null;
ptr = null;
}
// Commit Connection
conn.commit();
// 获得文件长度
sql = "select datalength(filecontent) from T1_TB_TestFile where FileUUID = '"
+ uuid + "'";
rs = stmt.executeQuery(sql);
if (rs.next()) ...{
size = rs.getLong(1);
logger.info("数据库写入的文件长度为: " + size);
}
// 获得 Image 类型的指针
sql = "select textptr(FileContent) from T1_TB_TestFile where FileUUID = '"
+ uuid + "'";
rs = stmt.executeQuery(sql);
if (rs.next()) ...{
ptr = rs.getBytes(1);
}
rs.close();
rs = null;
if (ptr != null) ...{
// 获得文件输出流
file = new File(OUTPUT_FILE);
if (file.exists()) ...{
file.delete();
}
output = new FileOutputStream(file);
// 偏移量置零
offset = 0;
// 读取 Image 类型字段,holdlock表示锁定以进行读取,直到事务结束为止。
sql = "readtext T1_TB_TestFile.FileContent ? ? ? holdlock";
pstmt = conn.prepareStatement(sql);
// 写入output流,<=表示已经写完
while (size > 0) ...{
// Image 类型的指针
pstmt.setBytes(1, ptr);
// 偏移量
pstmt.setInt(2, offset);
// 读出的长度
len = length < size ? length : (int) size;
pstmt.setInt(3, len);
// 将内容读出数据库
rs = pstmt.executeQuery();
if (rs.next()) ...{
buffer = rs.getBytes(1);
output.write(buffer);
}
// 清空参数
pstmt.clearParameters();
// 移动偏移量
offset += len;
size -= len;
}
pstmt.close();
pstmt = null;
// 关闭输出流
output.close();
output = null;
logger.info("数据库读出的文件长度为: " + file.length());
}
// Commit Connection
conn.commit();
conn.close();
conn = null;
} catch (Exception e) ...{
logger.error(e.getMessage(), e);
} finally ...{
// 依次关闭资源
if (rs != null) ...{
try ...{
rs.close();
} catch (SQLException e) ...{
logger.error(e.getMessage(), e);
}
rs = null;
}
if (stmt != null) ...{
try ...{
stmt.close();
} catch (SQLException e) ...{
logger.error(e.getMessage(), e);
}
stmt = null;
}
if (pstmt != null) ...{
try ...{
pstmt.close();
} catch (SQLException e) ...{
logger.error(e.getMessage(), e);
}
pstmt = null;
}
if (conn != null) ...{
try ...{
conn.rollback();
conn.close();
} catch (SQLException e) ...{
logger.error(e.getMessage(), e);
}
conn = null;
}
if (input != null) ...{
try ...{
input.close();
} catch (IOException e) ...{
logger.error(e.getMessage(), e);
}
input = null;
}
if (output != null) ...{
try ...{
output.close();
} catch (IOException e) ...{
logger.error(e.getMessage(), e);
}
output = null;
}
}
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.Statement;
import java.util.Properties;
import java.util.UUID;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
/**/ /*
* 测试利用 SQL Server 的 Image 类型存储文件,并从数据库取出数据存入文件
* 数据库表:
* T1_TB_TestFile
* 字段:
* [FileUUID] [char](36) NOT NULL
* [FileContent] [image] NULL
*/
public class TestMsSqlImage ... {
// Log4j Logger
private static Logger logger = Logger.getLogger(TestMsSqlImage.class);
// 数据库JDBC常量
private static String JDBC_DRIVER = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
private static String JDBC_URL = "jdbc:sqlserver://HOME-AMD";
private static String MSSQL_DATABASE = "test1";
private static String MSSQL_USER = "sa";
private static String MSSQL_PASSWORD = "123";
// 存入数据库的文件路径
private static String INPUT_FILE = "C:/Temp/生物课件.zip";
// 从数据库取出的文件路径
private static String OUTPUT_FILE = "C:/Temp/OUT.zip";
/** *//**
* 文件 -> 数据库 -> 文件
*
* @param args
*/
public static void main(String[] args) ...{
logger.setLevel(Level.ALL);
Connection conn = null;
Statement stmt = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
FileInputStream input = null;
FileOutputStream output = null;
try ...{
// 设置数据库属性
Properties properties = new Properties();
properties.setProperty("database", MSSQL_DATABASE);
properties.setProperty("user", MSSQL_USER);
properties.setProperty("password", MSSQL_PASSWORD);
// 传统JDBC获得连接
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(JDBC_URL, properties);
stmt = conn.createStatement();
// 随机获得唯一UUID
String uuid = UUID.randomUUID().toString();
// 生成一条数据库数据
sql = "insert into T1_TB_TestFile (FileUUID) values ('" + uuid
+ "')";
stmt.executeUpdate(sql);
// 即使在insert时插入image类型的值为null,数据库依然不会创建指针。可以使用update创建指针。
sql = "update T1_TB_TestFile set FileContent = null where FileUUID = '"
+ uuid + "'";
stmt.executeUpdate(sql);
// 创建缓冲区,微软建议最佳长度为8040的倍数
int length = 8040 * 100;
byte[] buffer = new byte[length];
// Image 类型的指针
byte[] ptr = null;
// 偏移量
int offset = 0;
// 读写字节数
int len = 0;
// 文件长度
long size = 0;
File file = null;
// 取消 Auto Commit
conn.setAutoCommit(false);
// 获得 Image 类型的指针
sql = "select textptr(FileContent) from T1_TB_TestFile where FileUUID = '"
+ uuid + "'";
rs = stmt.executeQuery(sql);
if (rs.next()) ...{
ptr = rs.getBytes(1);
}
rs.close();
rs = null;
if (ptr != null) ...{
// 获得文件输入流
file = new File(INPUT_FILE);
logger.info("磁盘上原始的文件长度为: " + file.length());
input = new FileInputStream(file);
// 更新 Image 类型字段,0表示不删除内容
sql = "updatetext T1_TB_TestFile.FileContent ? ? 0 ?";
pstmt = conn.prepareStatement(sql);
// 读取input流,-1表示已经读完
while ((len = input.read(buffer)) != -1) ...{
// Image 类型的指针
pstmt.setBytes(1, ptr);
// 偏移量
pstmt.setInt(2, offset);
// 写入的内容
pstmt.setBytes(3, buffer);
// 将读取内容写入数据库
pstmt.executeUpdate();
// 清空参数
pstmt.clearParameters();
// 移动偏移量
offset += len;
}
pstmt.close();
pstmt = null;
// 关闭输入流
input.close();
input = null;
// 删除多余内容,NULL 表示删除偏移量后所有内容
sql = "updatetext T1_TB_TestFile.FileContent ? ? NULL";
pstmt = conn.prepareStatement(sql);
pstmt.setBytes(1, ptr);
pstmt.setInt(2, offset);
pstmt.executeUpdate();
pstmt.close();
pstmt = null;
ptr = null;
}
// Commit Connection
conn.commit();
// 获得文件长度
sql = "select datalength(filecontent) from T1_TB_TestFile where FileUUID = '"
+ uuid + "'";
rs = stmt.executeQuery(sql);
if (rs.next()) ...{
size = rs.getLong(1);
logger.info("数据库写入的文件长度为: " + size);
}
// 获得 Image 类型的指针
sql = "select textptr(FileContent) from T1_TB_TestFile where FileUUID = '"
+ uuid + "'";
rs = stmt.executeQuery(sql);
if (rs.next()) ...{
ptr = rs.getBytes(1);
}
rs.close();
rs = null;
if (ptr != null) ...{
// 获得文件输出流
file = new File(OUTPUT_FILE);
if (file.exists()) ...{
file.delete();
}
output = new FileOutputStream(file);
// 偏移量置零
offset = 0;
// 读取 Image 类型字段,holdlock表示锁定以进行读取,直到事务结束为止。
sql = "readtext T1_TB_TestFile.FileContent ? ? ? holdlock";
pstmt = conn.prepareStatement(sql);
// 写入output流,<=表示已经写完
while (size > 0) ...{
// Image 类型的指针
pstmt.setBytes(1, ptr);
// 偏移量
pstmt.setInt(2, offset);
// 读出的长度
len = length < size ? length : (int) size;
pstmt.setInt(3, len);
// 将内容读出数据库
rs = pstmt.executeQuery();
if (rs.next()) ...{
buffer = rs.getBytes(1);
output.write(buffer);
}
// 清空参数
pstmt.clearParameters();
// 移动偏移量
offset += len;
size -= len;
}
pstmt.close();
pstmt = null;
// 关闭输出流
output.close();
output = null;
logger.info("数据库读出的文件长度为: " + file.length());
}
// Commit Connection
conn.commit();
conn.close();
conn = null;
} catch (Exception e) ...{
logger.error(e.getMessage(), e);
} finally ...{
// 依次关闭资源
if (rs != null) ...{
try ...{
rs.close();
} catch (SQLException e) ...{
logger.error(e.getMessage(), e);
}
rs = null;
}
if (stmt != null) ...{
try ...{
stmt.close();
} catch (SQLException e) ...{
logger.error(e.getMessage(), e);
}
stmt = null;
}
if (pstmt != null) ...{
try ...{
pstmt.close();
} catch (SQLException e) ...{
logger.error(e.getMessage(), e);
}
pstmt = null;
}
if (conn != null) ...{
try ...{
conn.rollback();
conn.close();
} catch (SQLException e) ...{
logger.error(e.getMessage(), e);
}
conn = null;
}
if (input != null) ...{
try ...{
input.close();
} catch (IOException e) ...{
logger.error(e.getMessage(), e);
}
input = null;
}
if (output != null) ...{
try ...{
output.close();
} catch (IOException e) ...{
logger.error(e.getMessage(), e);
}
output = null;
}
}
}
}