C++使用SQLite3心得 -- sqlite3以二进制形式存取图片(MFC,CppSQLite3U封装类)

实现功能:1.将图片文件(.jpg)以二进制形式存储到sqlite3里面
		2.从sqlite3里面读取二进制形式的图片数据并保存到图片文件(.jpg)

*注:本人超级菜鸟 此博客是为了总结用 仅仅说明了函数作用 可能直接编译不过 见谅 文中有何不妥之处 还望各位读者不吝赐教

一、创建/打开 sqlite3数据库 并 创建/打开 表

C++
// 打开sqlite3数据库(用CppSQLite3U类的方式)
	// 定义表名称
	#define TABLENAME _T("tb")
	
	// 声明数据库类型的全局变量
	CppSQLite3DB g_db;


	// 获取当前程序路径 并加上数据库名称
	CString strDbPath;
	CString strDbName(_T("test1.db"));
	GetCurrentDirectory( strDbPath );
	strDbPath += strDbName;


	// 创建/打开 数据库 若不存在则创建
	try{
		g_db.open(strDbPath);
	}
	catch(CppSQLite3Exception ex)
	{
		g_db.execDML(L"rollback transaction;");
	}
	
	// 创建表
	// 判断表名是否已经存在
	CString strTbSql;
	CString strTbName(TABLENAME);
	try{
		if(!g_db.tableExists(strTbName))
		{  
			// 不存在,新建表tb
			strTbSql.Format(_T("CREATE TABLE %s(ID INTEGER PRIMARY KEY, image BLOB);"), strTbName);
			
			// 执行SQL语句
			g_db.execDML(strTbSql);
			strTbSql.Empty();
			strTbSql.Format(_T("表%s创建成功!"), strTbName);
			::AfxMessageBox(strTbSql);
		}
		else
		{
			strTbSql.Format(_T("表%s已经存在!"), strTbName);
			::AfxMessageBox(strTbSql);
		}
	}
	catch(CppSQLite3Exception ex)
	{
		g_db.execDML(L"create table exception!");
	}

二、然后拿到图片文件 打开图片文件并保存到sqlite3数据库中

C++
// 把图片文件以二进制形式保存到sqlite3数据库中

	
	// 拿到C盘下pic1.jpg图片的路径
	CString strFilePath(_T("C:\\pic1.jpg"));

	// 读取图片并开辟一块缓冲区以二进制形式存放图片
	CFile file;
	file.Open(strFilePath, CFile::typeBinary | CFile::modeRead);
	int nFileSize = file.GetLength();
	BYTE *pbytBuffer = new BYTE[nFileSize];
	file.Read(pbytBuffer, nFileSize);


	// 创建SQL语句 并利用stmt准备完毕
	// CppSQLite3U 是从网上找的一个封装了sqlite3的类 百度即有
	CppSQLite3Statement stmt;
	CString strSqlInsert;
	strSqlInsert.Format(
	_T("INSERT INTO %s values(1, ?)"), TABLENAME);


	// 将缓冲区绑定  并存到SQLite的BLOB类型中
	stmt = g_db.compileStatement(strSqlInsert);
	stmt.bind(1, pbytBuffer, nFileSize);
	stmt.execDML();
	stmt.finalize();
	

三、从sqlite3中读取二进制数据 并将其保存为jpg文件

C++
// 读取文件的时候用到一个函数CppSQLite3Statement::execQuery(void)
// 不知什么原因    这个函数只有声明而没有实现   
//个人能力有限   不会给其实现   所以就用的sqlite3的api

	// 打开数据库
	sqlite3 *db;
	if( SQLITE_OK != sqlite3_open("test1.db", &db) )
	{
		if(IDOK == ::AfxMessageBox(_T("db open error!")))
			return;
	}
	
	// 读二进制数据时要用的变量
	sqlite3_stmt  *pStmt;	
	CString strSqlSelect;

	// 准备pStmt
	sqlite3_prepare( db, "select * from tb1 where ID=1;", -1, &pStmt, 0 );
	sqlite3_step(pStmt);

	// 获取BLOB字段存放内容的长度  第二个参数是左起从0开始的位置
	ULONG ulImageSize = sqlite3_column_bytes(pStmt, 1);/*该函数返回指定行的第'1'列的长度   第二个参数是列的标号   从左边开始   计数从0开始  所建表共2列   第一列为ID(integer)  第二列为image(BLOB) 所以应为'1'*/
	
	char *pBufferDst = new char[ulImageSize];
	memset(pBuffer, 0, ulImageSize);// 将缓冲区置零

	// 用pBuffer接收 sqlite中存放的BLOB类型的数据返回的缓冲区指针
	char *pBuffer = 
		(char *)sqlite3_column_blob(pStmt,1);/*该函数返回指定行的第'1'列的内容的缓冲区的指针   第二个参数介绍同上的sqlite3_column_bytes().*/

	// 将返回的缓冲区的内容拷贝到自己定义的缓冲区pBufferDst中
	memcpy(pBufferDst, pBuffer, ulImageSize);

	// 到这   sqlite3的相关资源就可以释放了
	sqlite3_finalize(pStmt);
	sqlite3_close(db);

	// 将缓冲区内保存的二进制数据保存到 jpg文件中
	CFile file;
	file.Open(_T("C:\\222.jpg"), CFile::typeBinary | CFile::modeWrite | CFile::modeCreate);
	file.Write(pBufferDst, ulImageSize);

	// 释放申请的堆内存资源
	delete[] pBufferDst;
	pbytBuffer = NULL;

    // 关闭文件
	file.Close();

四、最后在提供不用CppSQLite3U封装类的存储方式 – 简写了

C++
	// sqlite3 api 实现
	sqlite3 * db;
	int result;
	char buf[64];
	char *errmsg;
	errmsg = buf;
	
	// 打开数据库
	result = sqlite3_open("test.db", &db );

	// SQL语句
	char *sql = "CREATE TABLE tb(ID INTEGER, binData BLOB);";
	result = sqlite3_exec( db, sql, NULL, NULL, &errmsg);
	if(result != SQLITE_OK)
	{
		printf("Error : %s\n", errmsg);
	}

	// 写二进制数据时要用的结构
	sqlite3_stmt  *stmt;
	
	// 准备插入数据
	sqlite3_prepare( db, "insert into tb( ID,  binData) values( 20, ? );", -1, &stmt, 0 );
	
	// 把内容和字段绑定

	// 执行
	result=sqlite3_step( stmt );
	sqlite3_step( stmt );

	// 释放相关资源
	sqlite3_finalize( stmt );
	sqlite3_close( db );

*注:本人超级菜鸟 此博客是为了总结用 仅仅说明了函数作用 可能直接编译不过 见谅 文中有何不妥之处 还望各位读者不吝赐教

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
要在C++中更新SQLite3中的二进制数据,您可以使用SQLite3提供的BLOB类型。以下是一个简单的示例代码,它演示如何更新一个名为"my_table"的表中的二进制数据列"my_blob_column": ```c++ #include <sqlite3.h> #include <iostream> #include <fstream> using namespace std; int main() { // Open database sqlite3 *db; int rc = sqlite3_open("my_database.db", &db); if (rc != SQLITE_OK) { cerr << "Error opening database: " << sqlite3_errmsg(db) << endl; sqlite3_close(db); return 1; } // Read binary data from a file ifstream file("my_binary_data.bin", ios::binary | ios::ate); if (!file.is_open()) { cerr << "Error opening file." << endl; sqlite3_close(db); return 1; } streamsize size = file.tellg(); file.seekg(0, ios::beg); char *buffer = new char[size]; if (!file.read(buffer, size)) { cerr << "Error reading file." << endl; delete[] buffer; sqlite3_close(db); return 1; } file.close(); // Update binary data in database sqlite3_stmt *stmt; const char *sql = "UPDATE my_table SET my_blob_column = ? WHERE id = 1;"; rc = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); if (rc != SQLITE_OK) { cerr << "Error preparing statement: " << sqlite3_errmsg(db) << endl; delete[] buffer; sqlite3_close(db); return 1; } sqlite3_bind_blob(stmt, 1, buffer, size, SQLITE_TRANSIENT); rc = sqlite3_step(stmt); if (rc != SQLITE_DONE) { cerr << "Error updating data: " << sqlite3_errmsg(db) << endl; delete[] buffer; sqlite3_finalize(stmt); sqlite3_close(db); return 1; } // Cleanup delete[] buffer; sqlite3_finalize(stmt); sqlite3_close(db); return 0; } ``` 在这个示例中,我们首先打开了一个名为"my_database.db"的SQLite3数据库。然后,我们从一个名为"my_binary_data.bin"的文件中读取二进制数据,并将其存储在一个名为"buffer"的字符数组中。接下来,我们准备了一个SQL语句,使用"sqlite3_prepare_v2"函数编译该语句,并使用"sqlite3_bind_blob"函数绑定二进制数据到该语句中。最后,我们使用"sqlite3_step"函数执行该语句并更新数据库中的二进制数据。最后,我们清理并关闭数据库。 请注意,在这个示例中,我们使用了一个名为"SQLITE_TRANSIENT"的特殊标记来告诉SQLite3库,我们正在使用动态分配的内存来存储二进制数据。这意味着SQLite3库将复制这些数据,而不是仅仅在内部保存指向该数据的指针。这可以确保在更新期间,我们的内存不会被释放或修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值