/**
* 使用鍵盤輸入流,接收一大段文本數據,並輸入一個圖片的路徑, 然後將這些數據保存在數據表中,數據表由用戶自行創建。
*/
package exercise17;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DriverManager;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Ex03 {
public static final String DBDRIVER = "com.mysql.cj.jdbc.Driver";
public static final String DBURL = "jdbc:mysql://localhost:3306/test";
public static final String DBUSER = "root";
public static final String DBPASS = "mysqladmin";
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
Connection conn = null;
Class.forName(DBDRIVER); // 加載驅動程序
conn = DriverManager.getConnection(DBURL, DBUSER, DBPASS);
createTable(conn); // 創建名爲info的數據表
insertData(conn); // 向數據庫表中插入一行數據
showPhoto(conn); // 展示數據表中的數據內容,longtext類型數據打印在控制檯,二進制大對象(longblob類型)輸出到桌面的文件中
}
/**
*
* @return 用戶從鍵盤輸入的字符串
* @throws Exception
*/
public static String getString() throws Exception {
InputStreamReader isr = new InputStreamReader(System.in); // 創建字符輸入流實例,從鍵盤輸入
BufferedReader buf = new BufferedReader(isr); // 創建字符輸入流緩衝
String temp = null; // 保存用戶輸入的字符串
temp = buf.readLine(); // 從字符輸入流緩衝中讀取一行字符
return temp;
}
/**
* @param 數據庫的連接實例
* @throws Exception
* @function 向數據庫中插入一行數據
*/
public static void insertData(Connection conn) throws Exception {
boolean flag = true; // 定義一個標識符
InputStream input = null; // 定義一個字節輸入流
PreparedStatement pstmt = null; // 數據庫操作
// 定義向數據庫中插入數據的SQL語句
String sql = "INSERT INTO info(note, photo) VALUES(?, ?)";
pstmt = conn.prepareStatement(sql); // 獲取數據庫操作實例
while (flag) { // 反覆插入數據,直至標識符爲false
String text = getLargeText("請輸入一個大文本數據:"); // 提示用戶輸入longtext類型的大文本數據
byte[] b = text.getBytes(); // 將文本數據從字符串轉換爲byte類型的數組b
input = new ByteArrayInputStream(b); // 創建字節數組輸入流,將字節數組b傳入輸入流
pstmt.setAsciiStream(1, input); // 設置SQL語句中的第一個?的值
// 提示用戶輸入要保存的圖片(longblob類型)路徑,返回該文件的File實例
File f = getPhotoDir("請輸入一張圖片的保存路徑:", "路徑錯誤,請重新輸入:");
input = new FileInputStream(f); // 創建文件的輸入流
pstmt.setBinaryStream(2, input); // 設置SQL語句中的第二個?的值
pstmt.executeUpdate(); // 向數據庫中的info表中插入數據
System.out.println("是否繼續更新數據?結束請輸入‘N’:");
String str = "";
if ((str = getString()).equals("N") || str.equals("n")) { // 如果用戶輸入了n(部分大小寫),則將標識符改爲false結束更新
flag = false;
}
}
}
/**
*
* @param 提示信息
* @return 字符串(用戶輸入的大文本數據內容)
* @throws Exception
*/
public static String getLargeText(String info) throws Exception {
System.out.println(info); // 打印提示信息
StringBuffer buffer = new StringBuffer(); // 創建字符串緩衝
String str = "";
// 用戶可多行輸入字符串(刪除字符串兩端的空格被刪除),直到輸入end爲止(建議用戶輸入圖片文件的名稱,這樣在讀取時可以利用note列獲得文件名稱)
while (!(str = getString().trim()).equals("end")) {
buffer.append(str).append("\r\n"); // 每輸入一行就加入到StringBuffer中
}
buffer.delete(buffer.length()-2, buffer.length()); // 當結束輸入時,將最後面多餘的換行符(\r和\n兩個字符)刪除
return buffer.toString(); // 以字符串形式返回
}
/**
*
* @param info:輸入提示
* @param err:錯誤提示
* @return 用戶輸入的文件路徑的File實例
* @throws Exception
*/
public static File getPhotoDir(String info, String err) throws Exception {
System.out.println(info); // 打印輸入提示
String path = getString(); // 獲得文件路徑的一個字符串
File f = null;
f = new File(path); // 獲得文件的File實例
while (!f.exists() || !path.matches(".+\\.(jpg|png|jpeg|gif)")) { // 判斷文件是否存在,或文件格式(圖片)是否正確
System.err.println(err); // 如果判斷結果爲否,則打印錯誤提示
path = getString(); // 重新輸入
f = new File(path); // 重新創建File實例
}
return f; // 返回正確的文件File實例
}
/**
*
* @param conn:數據庫連接實例
* @throws SQLException
* @function 在數據庫中創建數據表info(如果這個類型的表已經存在就不用重複創建了)
*/
public static void createTable(Connection conn) throws SQLException {
Statement stmt = null; // 數據庫操作
stmt = conn.createStatement(); // 通過數據庫連接得到數據庫操作實例
// 定義SQL語句,該語句的內容就是:創建數據表info(如果表不存在)。
String sql = "create table if not exists info("
+ "id int auto_increment primary key," // id列,自動增長、主鍵
+ "note varchar(30) CHARACTER SET gbk DEFAULT NULL," // note列,大文本數據對象
+ "photo longblob" // photo列,二進制大數據對象(圖片)
+ ");";
stmt.execute(sql); // 執行SQL語句,創建info表
}
/**
* @function 展示數據表中的全部數據內容,longtext類型數據打印在控制檯,二進制大對象(longblob類型)輸出到桌面的文件中
* @param conn: 數據庫連接實例
* @throws Exception
*/
public static void showPhoto(Connection conn) throws Exception {
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = "SELECT id, note, photo FROM info;";
pstmt = conn.prepareStatement(sql); // 獲得數據庫操作實例
rs = pstmt.executeQuery(); // 實行SQL語句,得到查詢的結果集
while (rs.next()) { // 展示結果集中的全部內容
int id = rs.getInt("id"); // 獲得id的值
Clob clob = rs.getClob("note"); // 從結果集中獲得大文本數據
String note = clob.getSubString(1, (int)clob.length()); // 轉換成字符串
System.out.println("id: " + id + "; note: " + note); // 輸出id和note內容
File f = new File("C:" + File.separator + "Users" + File.separator + "yeqin" +
File.separator + "Desktop" + File.separator + note + ".gif"); // 得到輸出文件的路徑(在桌面)
if (!f.exists()) { // 如果輸出的文件不存在,則新建一個
System.out.println("在" + f.toString() + "處新建一個文件!");
f.createNewFile(); // 新建一個文件
}
OutputStream output = new FileOutputStream(f); // 得到文件的寫入流
Blob blob = rs.getBlob("photo"); // 從結果集中獲得Blob實例
byte[] b = blob.getBytes(1, (int)blob.length()); // 將Blob實例中的數據保存在byte類型數組中,注意Blob實例的起始位置爲1,而不是0
output.write(b); // 將數組內容寫入文件中
output.close();
}
pstmt.close();
}
}
/**
* 程序運行結果:
請輸入一個大文本數據:
red flower
end
請輸入一張圖片的保存路徑:
d:\photo\red flower.gif
是否繼續更新數據?結束請輸入‘N’:
y
請輸入一個大文本數據:
HeloIcon_solid
end
請輸入一張圖片的保存路徑:
y
路徑錯誤,請重新輸入:
d:\photo\HelpIcon_solid.gif
是否繼續更新數據?結束請輸入‘N’:
y
請輸入一個大文本數據:
image1
end
請輸入一張圖片的保存路徑:
d:\photo\image1.gif
是否繼續更新數據?結束請輸入‘N’:
n
id: 1; note: red flower
在"C:\Users\yeqin\Desktop\red flower.gif"處新建一個文件!
id: 2; note: HeloIcon_solid
在"C:\Users\yeqin\Desktop\HeloIcon_solid.gif"處新建一個文件!
id: 3; note: image1
在"C:\Users\yeqin\Desktop\image1.gif"處新建一個文件!
*
*/