版权声明:本文为CSDN博主「intfre」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/nibiru_holmes/article/details/51387047
0x01
首先MySQL支持二进制的类型有Blob:
MySQL的四种BLOB类型
类型 大小(单位:字节)
- TinyBlob 最大 255
- Blob 最大 65K
- MediumBlob 最大 16M
- LongBlob 最大 4G
0x02
插入二进制数据时需要利用mysql_real_escape_string函数对数据进行转换
0x03
读取二进制数据时需要利用mysql_fetch_length函数字段长度, 该函数需要在mysql_fetch_row调用后才可以正常获取结果
0x04
写入例子:
int CFinger_PrintDlg::Connect_Mysql(byte b_name[], byte* b_data,int len_of_data) {
const char user[] = "root";
const char pswd[] = "toor";
const char host[] = "127.0.0.1";
const char db[] = "Fingerprint";
int res;
int listrow = 0;
char sql_buf[100] = {};
unsigned int port = 3306;
bool return_result = false;
MYSQL myCont;
MYSQL_RES *result;
MYSQL_ROW sql_row;
HWND hWnd = GetSafeHwnd();
TCHAR sql_buf_t[100] = {};
//CListCtrl* list = (CListCtrl*)GetDlgItem(IDC_LIST3);
mysql_init(&myCont);
if (mysql_real_connect(&myCont, host, user, pswd, db, port, NULL, 0))
{
PostMessage(WM_MyMessage, (WPARAM)&L"连接数据库成功!!", (LPARAM)NULL);
}
mysql_query(&myCont, "SET NAMES GBK"); //设置编码格式
char buf[2000] = { NULL };
unsigned int escape_size = 2 * len_of_data + 2;
char* escape_object = (char *)malloc(escape_size);
escape_size = mysql_real_escape_string(&myCont, (char*)escape_object, (char *)b_data, len_of_data);
int sql_len = sprintf_s(buf, "insert into finger3(info) values('%s')", escape_object);
res = mysql_real_query(&myCont,buf, sql_len);
if (!res)
{
return_result = TRUE;
if (!res)
{
PostMessage(WM_MyMessage, (WPARAM)L"写入成功", NULL);
}
}
else
{
PostMessage(WM_MyMessage, (WPARAM)L"写入失败", NULL);
}
mysql_close(&myCont);
return return_result;
}
0x05
读取操作:
void* CFinger_PrintDlg::Read_Mysql()
{
if (!g_connect){
SendMessage(WM_MyMessage, (WPARAM)L"数据库未连接…", NULL);
return 0;
}
MYSQL_RES *res = NULL;
MYSQL_ROW row;
unsigned long *row_len;
char *object = NULL;
//const char *sql = "select info from final where id=";
char sql[100] = { NULL };
unsigned long objsize;
int ret;
for (int i = 1; i <= 10; i++){
sprintf_s(sql, "select info from final where id='%d'", i);
ret = mysql_real_query(&myCont, sql, strlen(sql));
if (ret){
PostMessage(WM_MyMessage, (WPARAM)L"读取失败1", NULL);
}
res = mysql_store_result(&myCont);
if (res == NULL){
PostMessage(WM_MyMessage, (WPARAM)L"读取失败2", NULL);
}
/* important */
row = mysql_fetch_row(res);
row_len = mysql_fetch_lengths(res); /* get the object's length */
if (row_len == NULL){
PostMessage(WM_MyMessage, (WPARAM)L"读取失败3", NULL);
}
objsize = row_len[0];
object = (char*)malloc(objsize);
if (object == NULL){
PostMessage(WM_MyMessage, (WPARAM)L"读取失败4", NULL);
}
memcpy(object, row[0], objsize);
if (BIOKEY_DB_ADD(ZKFingerHandle, i, objsize, (byte*)object)){
PostMessage(WM_MyMessage, (WPARAM)L"读取成功", NULL);
}
}
g_connect = false;
;
//mysql_close(&myCont);
mysql_free_result(res);
return NULL;
}
0x06
更新操作:
int CFinger_PrintDlg::Updata_Mysql(byte b_name[], byte* b_data, int len_of_data){
if (!g_connect){
SendMessage(WM_MyMessage, (WPARAM)L"数据库未连接...", NULL);
return 0;
}
int res;
bool return_result = false;
mysql_query(&myCont, "SET NAMES GBK"); //设置编码格式
char buf[2000] = { NULL };
unsigned int escape_size = 2 * len_of_data + 2;
char* escape_object = (char *)malloc(escape_size);
escape_size = mysql_real_escape_string(&myCont, (char*)escape_object, (char *)b_data, len_of_data);
CString id_cs;
CString name_cs;
int id;
char name[20] = { NULL };
GetDlgItem(IDC_EDIT1)->GetWindowTextW(id_cs);
GetDlgItem(IDC_EDIT2)->GetWindowTextW(name_cs);
id = _wtoi(id_cs);
WideCharToMultiByte(CP_ACP, 0, name_cs, -1, name, name_cs.GetLength(), NULL, NULL);
//int sql_len = sprintf_s(buf, "insert into final(id,name,info) values('%d','%s','%s')", id, name, escape_object);
//UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
int sql_len = sprintf_s(buf, "UPDATE final SET name='%s',info='%s' where id ='%d'", name, escape_object, id);
res = mysql_real_query(&myCont, buf, sql_len);
if (!res)
{
return_result = TRUE;
if (!res)
{
PostMessage(WM_MyMessage, (WPARAM)L"更新成功", NULL);
}
}
else
{
PostMessage(WM_MyMessage, (WPARAM)L"更新失败", NULL);
}
//mysql_close(&myCont);
g_connect = false;
return return_result;
}
C/C++ 开发(学习笔记八):Mysql数据库图片存储
1.准备好一张图片文件,将图片read,存放到buffer
2.将图片数据(buffer)写入mysql
3.从mysql中读取图片数据(buffer)
4.将图片数据(buffer)写入磁盘
一、读入图片
//读取图片
//filename:path+file name
//buffer:store image data
int read_image(char* filename,char* buffer){
if(filenameNULL||bufferNULL) return -1;
FILE *fp=fopen(filename,“rb”);
if(fp==NULL){
printf(“fopen faild\n”);
return -2;
}
//file size
fseek(fp,0,SEEK_END);//把文件指针置到末尾
int length=ftell(fp);//返回当前文件流的指针位置,也就是偏移量,文件大小file size
fseek(fp,0,SEEK_SET);//把文件指针置到开头
int size=fread(buffer,1,length,fp);//每次读1个字节,读length次。读取的参数放到buffer里
if(size!=length){
printf(“fread faild\n”);
return -3;
}
fclose(fp);
return size;
}
二、图片数据写入磁盘
//图片写入到磁盘(参数1:保存的文件名 参数2:要写的数据 参数3:数据长度)
int write_image(char* filename,char* buffer,int length){
if(filenameNULL||bufferNULL||length<=0) return -1;
FILE *fp=fopen(filename,“wb+”);//w表示写入 b表示二进制 +表示,如果文件不存在则会创建,存在则会直接写入
if(fp==NULL){
printf(“fopen faild\n”);
return -2;
}
int size=fwrite(buffer,1,length,fp);//从buffer写到fp中,每次写1个字节,写length次
if(size!=length){
printf(“fwirte failded:%d\n”,size);
return -3;
}
fclose(fp);
return size;
}
三、表中增加图片数据一列
在表中加一列U_IMG,存放图片数据
ALTER TABLE TBL_USER ADD U_IMG BLOB;
1
变成下面这样
四、将图片数据存入Mysql服务器
MySQL C语言接口-预处理语句
mysql stmt语法_mysql中SQL执行过程详解与用于预处理语句的SQL语法
//插入图片的SQL语句,由于不知道传入的图片是什么,用?作为占位符
#define SQL_INSERT_IMG_USER “insert TBL_USER(U_NAME,U_GENDER,U_IMG) value(‘Dog’,‘man’,?);”
int mysql_write(MYSQL* handle,char* buffer,int length){
if(handleNULL||bufferNULL||length<=0) return -1;
MYSQL_STMT *stmt=mysql_stmt_init(handle);//在mysql中创建一个存储空间
int ret=mysql_stmt_prepare(stmt,SQL_INSERT_IMG_USER,strlen(SQL_INSERT_IMG_USER));
if(ret){
printf("mysql_stmt_prepare:%s\n",mysql_error(handle));
return -2;
}
MYSQL_BIND param={0};
param.buffer_type=MYSQL_TYPE_LONG_BLOB;
param.buffer=NULL;
param.is_null=0;
param.length=NULL;
ret=mysql_stmt_bind_param(stmt,¶m);
if(ret){
printf("mysql_stmt_bind_param:%s\n",mysql_error(handle));
return -3;
}
ret=mysql_stmt_send_long_data(stmt,0,buffer,length);//允许应用程序分块地将参数数据发送到服务器
if(ret){
printf("mysql_stmt_send_long_data:%s\n",mysql_error(handle));
return -4;
}
ret=mysql_stmt_execute(stmt);//将当前绑定的参数标记符的值发送到服务器,服务器用新提供的数据替换标记符
if(ret){
printf("mysql_stmt_execute:%s\n",mysql_error(handle));
return -5;
}
ret=mysql_stmt_close(stmt);
if(ret){
printf("mysql_stmt_close:%s\n",mysql_error(handle));
return -6;
}
return ret;
}
五、将图像数据从Mysql服务器中取出
#define SQL_SELECT_IMG_USER “SELECT U_IMG FROM TBL_USER WHERE U_NAME=‘Dog’;”
int mysql_read(MYSQL* handle,char* buffer,int length){
if(handleNULL||bufferNULL||length<=0) return -1;
MYSQL_STMT *stmt=mysql_stmt_init(handle);//在mysql中创建一个存储空间
int ret=mysql_stmt_prepare(stmt,SQL_SELECT_IMG_USER,strlen(SQL_SELECT_IMG_USER));
if(ret){
printf("mysql_stmt_prepare:%s\n",mysql_error(handle));
return -2;
}
MYSQL_BIND result={0};
result.buffer_type=MYSQL_TYPE_LONG_BLOB;
unsigned long total_length=0;
result.length=&total_length;
ret=mysql_stmt_bind_result(stmt,&result);
if(ret){
printf("mysql_stmt_bind_result:%s\n",mysql_error(handle));
return -3;
}
ret=mysql_stmt_execute(stmt);//执行后,长度数据会存储到total_length中
if(ret){
printf("mysql_stmt_execute:%s\n",mysql_error(handle));
return -4;
}
//数据从管道里拿出来
ret=mysql_stmt_store_result(stmt);
if(ret){
printf("mysql_stmt_store_result:%s\n",mysql_error(handle));
return -5;
}
while(1){
ret=mysql_stmt_fetch(stmt);
if(ret!=0&&ret!=MYSQL_DATA_TRUNCATED) break;
int start=0;
while(start<(int)total_length){
result.buffer=buffer+start;
result.buffer_length=1;//每次读取得长度为1
mysql_stmt_fetch_column(stmt,&result,0,start);
start+=result.buffer_length;
}
}
mysql_stmt_close(stmt);
return total_length;
}
六、完整代码
#include<mysql.h>
#include<stdio.h>
#include<string.h>
#define KING_DB_SERVER_IP “192.168.192.128” //ip
#define KING_DB_SERVER_PORT 3306 //端口号
#define KING_DB_USERNAME “admin” //用户名
#define KING_DB_PASSWORD “123456” //密码
#define KING_DB_DEFAULTDB “KING_DB” //数据库名
//插入图片的SQL语句,由于不知道传入的图片是什么,用?作为占位符
#define SQL_INSERT_IMG_USER “insert TBL_USER(U_NAME,U_GENDER,U_IMG) value(‘Dog’,‘man’,?);”
#define SQL_SELECT_IMG_USER “SELECT U_IMG FROM TBL_USER WHERE U_NAME=‘Dog’;”
#define FILE_IMAGE_LENGTH (64*1024)
//读取图片
//filename:path+file name
//buffer:store image data
int read_image(char* filename,char* buffer){
if(filenameNULL||bufferNULL) return -1;
FILE *fp=fopen(filename,“rb”);
if(fp==NULL){
printf(“fopen faild\n”);
return -2;
}
//file size
fseek(fp,0,SEEK_END);//把文件指针置到末尾
int length=ftell(fp);//返回当前文件流的指针位置,也就是偏移量,文件大小file size
fseek(fp,0,SEEK_SET);//把文件指针置到开头
int size=fread(buffer,1,length,fp);//每次读1个字节,读length次。读取的参数放到buffer里
if(size!=length){
printf(“fread faild\n”);
return -3;
}
fclose(fp);
return size;
}
//图片写入到磁盘(参数1:保存的文件名 参数2:要写的数据 参数3:数据长度)
int write_image(char* filename,char* buffer,int length){
if(filenameNULL||bufferNULL||length<=0) return -1;
FILE *fp=fopen(filename,“wb+”);//w表示写入 b表示二进制 +表示,如果文件不存在则会创建,存在则会直接写入
if(fp==NULL){
printf(“fopen faild\n”);
return -2;
}
int size=fwrite(buffer,1,length,fp);//从buffer写到fp中,每次写1个字节,写length次
if(size!=length){
printf(“fwirte failded:%d\n”,size);
return -3;
}
fclose(fp);
return size;
}
int mysql_write(MYSQL* handle,char* buffer,int length){
if(handleNULL||bufferNULL||length<=0) return -1;
MYSQL_STMT *stmt=mysql_stmt_init(handle);//在mysql中创建一个存储空间
int ret=mysql_stmt_prepare(stmt,SQL_INSERT_IMG_USER,strlen(SQL_INSERT_IMG_USER));
if(ret){
printf("mysql_stmt_prepare:%s\n",mysql_error(handle));
return -2;
}
MYSQL_BIND param={0};
param.buffer_type=MYSQL_TYPE_LONG_BLOB;
param.buffer=NULL;
param.is_null=0;
param.length=NULL;
ret=mysql_stmt_bind_param(stmt,¶m);
if(ret){
printf("mysql_stmt_bind_param:%s\n",mysql_error(handle));
return -3;
}
ret=mysql_stmt_send_long_data(stmt,0,buffer,length);//允许应用程序分块地将参数数据发送到服务器
if(ret){
printf("mysql_stmt_send_long_data:%s\n",mysql_error(handle));
return -4;
}
ret=mysql_stmt_execute(stmt);//将当前绑定的参数标记符的值发送到服务器,服务器用新提供的数据替换标记符
if(ret){
printf("mysql_stmt_execute:%s\n",mysql_error(handle));
return -5;
}
ret=mysql_stmt_close(stmt);
if(ret){
printf("mysql_stmt_close:%s\n",mysql_error(handle));
return -6;
}
return ret;
}
int mysql_read(MYSQL* handle,char* buffer,int length){
if(handleNULL||bufferNULL||length<=0) return -1;
MYSQL_STMT *stmt=mysql_stmt_init(handle);//在mysql中创建一个存储空间
int ret=mysql_stmt_prepare(stmt,SQL_SELECT_IMG_USER,strlen(SQL_SELECT_IMG_USER));
if(ret){
printf("mysql_stmt_prepare:%s\n",mysql_error(handle));
return -2;
}
MYSQL_BIND result={0};
result.buffer_type=MYSQL_TYPE_LONG_BLOB;
unsigned long total_length=0;
result.length=&total_length;
ret=mysql_stmt_bind_result(stmt,&result);
if(ret){
printf("mysql_stmt_bind_result:%s\n",mysql_error(handle));
return -3;
}
ret=mysql_stmt_execute(stmt);//执行后,长度数据会存储到total_length中
if(ret){
printf("mysql_stmt_execute:%s\n",mysql_error(handle));
return -4;
}
//数据从管道里拿出来
ret=mysql_stmt_store_result(stmt);
if(ret){
printf("mysql_stmt_store_result:%s\n",mysql_error(handle));
return -5;
}
while(1){
ret=mysql_stmt_fetch(stmt);
if(ret!=0&&ret!=MYSQL_DATA_TRUNCATED) break;
int start=0;
while(start<(int)total_length){
result.buffer=buffer+start;
result.buffer_length=1;//每次读取得长度为1
mysql_stmt_fetch_column(stmt,&result,0,start);
start+=result.buffer_length;
}
}
mysql_stmt_close(stmt);
return total_length;
}
int main(){
MYSQL mysql;
if(!mysql_init(&mysql)){//mysql初始化并判断是否出错(返回0为失败)
printf(“mysql_init:%s\n”,mysql_error(&mysql));//mysql_error() 函数返回上一个 MySQL 操作产生的文本错误信息
return -1;
}
if(!mysql_real_connect(&mysql,KING_DB_SERVER_IP,KING_DB_USERNAME,KING_DB_PASSWORD,
KING_DB_DEFAULTDB,KING_DB_SERVER_PORT,NULL,0)){ //连接mysql数据库,并判断是否出错(返回0为失败)
printf(“mysql_real_connect:%s\n”,mysql_error(&mysql));
return -2;
}
printf("case:mysql --> read image and write mysql\n");
char buffer[FILE_IMAGE_LENGTH]={0};
int length = read_image("0voice.jpg",buffer);
if(length<0) goto Exit;
mysql_write(&mysql,buffer,length);
printf("case:mysql-->read mysql and write image\n");
memset(buffer,0,FILE_IMAGE_LENGTH);
length=mysql_read(&mysql,buffer,FILE_IMAGE_LENGTH);
write_image("a.jpg",buffer,length);
Exit:
mysql_close(&mysql);
return 0;
}