sqlite3的圖片的(二進制數據)存取操作
前言
上篇介紹了sqlite3的一些常用插入操作方法和注意事項,在實際項目中遇到了圖片緩存的問題,由於服務器不是很穩定,且受到外界環境的干擾(例如斷電,圖片存儲掛掉,圖片存儲速度過慢,造成的接口調用失敗等等),一個數據結構中除了普通字段(int string),還包括圖片數據,所以還需要將圖片數據進行緩存,圖片緩存與普通的數據庫字段值緩存有所不同,下面介紹一下簡單方法。
開發示例
此demo僅供學習使用。
sqlite3支持對二進制數據的緩存,在實際的編程開發當中我們經常要處理一些大容量二進制數據的存儲,如圖片、音樂、視頻等等。對於這些二進制數據,我們不能像處理普通的文本那樣,但是我們可以用blob來存儲。sqlite官方文檔https://www.sqlite.org/datatype3.html#section_1對blob 字段的解釋是
BLOB. The value is a blob of data, stored exactly as it was input。
即數據不做任何轉換,以輸入形式存儲。因此 BOLB通常用來存儲二進制大對象。
sqlite3_bind_blob示例代碼
char* cmdCreatBlobTable = "create table SqliteBlobTest (id integer , pic blob); //首先創建一個可插入blob類型的表 。
sqlite3* db = NULL;
char * errorMessage = NULL;
int iResult = sqlite3_open("SqliteTest.db", &db);
sqlite3_exec(db,"drop table if exists SqliteBlobTest",0,0,0);
iResult = sqlite3_exec(db, cmdCreatBlobTable, NULL, NULL, &errorMessage);
if (SQLITE_OK != iResult)
{
cout<<"創建表SqliteBlobTest失敗"<<endl;
break;
}
sqlite3_stmt *stmt; //聲明
const char* sql = "insert into SqliteBlobTest values(1,?)";
char* pPicData = "this is a pic data" ;
sqlite3_prepare(db,sql,strlen(sql),&stmt,0); //完成對sql語句的解析
{
sqlite3_bind_blob(stmt,1,pPicData, strlen(pPicData), NULL);//1代表第一個?
sqlite3_step(stmt); //將數據寫入數據庫中
}
sqlite3_prepare(db, "select * from SqliteBlobTest", -1, &stmt, 0);
int result = sqlite3_step(stmt);
int id = 0,len = 0;
char picData[128] = {0};
if (result == SQLITE_ROW) //查詢成功返回的是SQLITE_ROW
{
cout<<"read success from sqlite"<<endl;
id = sqlite3_column_int(stmt, 0); //從0開始計算,id為0,picdata 為1;
const void * pReadPicData = sqlite3_column_blob(stmt, 1); //讀取數據,返回一個指針
len = sqlite3_column_bytes(stmt, 1); //返回數據大小
memcpy(picData, pReadPicData, len); //把數據拷貝出來
}
else
{
cout<<"read fail from sqlite"<<endl;
}
sqlite3_finalize(stmt); //把剛才分配的內容析構掉
cout<<id<<" "<<picData<<endl;
測試結果
總結
經過這一個月工作之余的優化,終於把項目的緩存給做好了,其中也遇到了很多問題,例如sqlite的編碼轉換,圖片緩存速度慢,還有db-journal文件操作慢,以及如何直觀的讓sqliteDb大小自動展現,自己也是查了官方英文文檔才一步步解決各種坑。總結的好處就在於能夠溫故知新。