C++ 二进制图片的读取和blob插入mysql_stmt_init—新年第一课

关于二进制图片的读取和BLOB插入一共包含五步

第一步:初始化

MYSQL_STMT* stmt = mysql_stmt_init(&mysql);

第二步:预处理sql语句

mysql_stmt_prepare(stmt,sql,sqllen);

第三步:绑定字段

mysql_stmt_bind_param(stmt,bind);

第四步:执行

mysql_stmt_excute(stmt);

第五步:关闭

mysql_stmt_close(stmt);

详细步骤如下:

1、连接数据库;这个就不详细讲解了

const char* host = "127.0.0.1";const char* user = "root";const char* password = "************";const char* database = "database_test";int port = 3306;MYSQL mysql;mysql_init(&mysql);mysql_library_init(0, NULL, NULL);//防止乱码mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "GBK");//支持多条sql语句 CLIENT_MULTI_STATEMENTS   clientflag  默认是不支持的//if (!mysql_real_connect(&mysql, host, user, password, database, port, 0, 0))if (!mysql_real_connect(&mysql, host, user, password, database, port, NULL, 0)){cout << "failed to connect" << host << mysql_error(&mysql) << endl;}else{cout << "successfully connected " << host <<endl;}

2、创建数据表t_data; 创建好存放二进制数据的表 t_data

注意***:这里的数据类型,必须是blob其他和以前一样

//创建号存放二进制数据的表 t_datastring sql = "";sql="CREATE TABLe IF NOT EXISTS `t_data`(\`id` int AUTO_INCREMENT,\`name` varchar(1024),\`data` blob,\`size` int,\PRIMARY KEY(id)\)";int re = mysql_query(&mysql, sql.c_str());if (re != 0){cout << "failed mysql_error" << mysql_error(&mysql) << endl;}

3、初始化stmt

MYSQL_STMT*stmt=mysql_stmt_init(&mysql);

4、预处理sql语句

// 注意这里的插入必须是???
sql="insert into t_data (name,data,size) values (?,?,?)";

//错误输出是mysql_stmt_error(stmt);和之前不一样哦;

//sql语句,插入数据
// 注意这里的插入必须是???sql = "insert into `t_data` (name,data,size) values (?,?,?)";if (mysql_stmt_prepare(stmt, sql.c_str(), sql.size())){cerr << "mysql_stmt_prepare failed!" << mysql_stmt_error(stmt) << endl;}

5、绑定字段

MYSQL_BIND bind[3]={ 0 };//第一个数据name
bind[0].buffer_type = MYSQL_TYPE_STRING; //name文件名
bind[0].buffer = (char*)filename.c_str();//原图的文件名
bind[0].buffer_length = filename.size();
//(char*) buffer要求的是void*,而c_str()是只读的,所以要转换char*。
//而bind是可以输入可以输出,所以不可以只读。默认const是只读的,但是在这儿是插入数据,不会修改数据,可以用char*bind[1].buffer_type = MYSQL_TYPE_BLOB;// data 文件二进制内容
bind[1].buffer = data; //二进制文件
bind[1].buffer_length = filesize; //文件大小//把文件大小存下来
//从mysql取出来,可以知道文件大小,但是不一定将它取出来,
//经常做显示文件列表,有时候不需要显示二进制。希望有个字段将文件大小存下来bind[2].buffer_type = MYSQL_TYPE_LONG;//长整型,不用直到size,因为是固定大小
bind[2].buffer = &filesize;  //存放指针

5.1、如何filename 和data?

在上述代码的前面需要定义filename和data大小;

//4、打开并读取文件string filename = "mysql.jpg";//打开文件可以有多种方式,可以用c的file fopen,但是这个在vs2017里面说不安全,得设置不安全选项//fopen_s 是多线程安全版本的,到了linux又不行了//为了跨平台,用C++方式读取 fstream//需要知道文件大小和文件二进制  考虑到空间的分配和释放 动态空间//int filesize = 0;//ios::binary必须写,因为是二进制文件,如果是文本文件,无所谓不用加,但是还是加着fstream in(filename, ios::in | ios::binary);//文件是否存在if (!in.is_open()){cerr << "file" << filename << "open failed" << endl;}//fopen//句柄,文件指针移到结尾处//从结尾往前移动,移动0个位置,也就是结尾//判断位置in.seekg(0, ios::end);// 得到文件大小,//文件大小和文件二进制int filesize = in.tellg();//得到大小之后,将文件移到开头,要不然待会读文件就读不到了in.seekg(0, ios::beg);//分配空间大小char* data = new char[filesize];//查看是否读完,不保证一次读完,所以用循环读,可以直到读取了多少int readed = 0;//已经读了多少while (!in.eof()){//in.read(data, filesize); data读什么数据,filesize读多少//指针要进行移位in.read(data + readed, filesize - readed);//上次读了多少字节if (in.gcount()<=0){break;}readed += in.gcount();}in.close();

6、绑定 mysql_stmt_bind_param(stmt, bind)

//6、绑定if (mysql_stmt_bind_param(stmt, bind)!=0) //定义和文档不一致,=表示成功{//cerr错误输出,在重定向的时候,可以分割开来,也可以写到文件当中//cout 标准输出/*cout:写到标准输出的ostream对象;cerr:输出到标准错误的ostream对象,常用于程序错误信息;clog:也是输出标准错误流(这点儿和cerr是一样的),貌似平时很少用到这个啊;*/cerr << "mysql_stmt_bind_param failed" << mysql_stmt_error(stmt) << endl;}

7、执行stmt sql

//7、执行stmt sqlif (mysql_stmt_execute(stmt) != 0){//cerr错误输出cerr << "mysql_stmt_execute failed" << mysql_stmt_error(stmt) << endl;}

8、关闭stmt

mysql_stmt_close(stmt);

9、注意****

9.1、刚才申请了data空间是动态控件,必须要释放

delete []data;

9.2、在读取文件之后,一定要把文件关闭

in.close();

完整代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<mysql.h>
#include<thread>
#include<map>
#include<sstream>
#include<fstream>
//计时
#include<chrono>
using namespace std;
using namespace chrono;int main()
{const char* host = "127.0.0.1";const char* user = "root";const char* password = "*********"; //输入自己数据库的密码const char* database = "database_test";int port = 3306;MYSQL mysql;mysql_init(&mysql);mysql_library_init(0, NULL, NULL);//防止乱码mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "GBK");//支持多条sql语句 CLIENT_MULTI_STATEMENTS   clientflag  默认是不支持的//if (!mysql_real_connect(&mysql, host, user, password, database, port, 0, 0))if (!mysql_real_connect(&mysql, host, user, password, database, port, NULL, 0)){cout << "failed to connect" << host << mysql_error(&mysql) << endl;}else{cout << "successfully connected " << host <<endl;}//blob  blob存放二进制// int 最大值大概是2g//1、创建号存放二进制数据的表 t_datastring sql = "";sql="CREATE TABLe IF NOT EXISTS `t_data`(\`id` int AUTO_INCREMENT,\`name` varchar(1024),\`data` blob,\`size` int,\PRIMARY KEY(id)\)";int re = mysql_query(&mysql, sql.c_str());if (re != 0){cout << "failed mysql_error" << mysql_error(&mysql) << endl;}//2、初始化MYSQL_STMT* stmt = mysql_stmt_init(&mysql);//3、预处理sql语句sql = "insert into `t_data` (name,data,size) values (?,?,?)";if (mysql_stmt_prepare(stmt, sql.c_str(), sql.size())){cerr << "mysql_stmt_prepare failed!" << mysql_stmt_error(stmt) << endl;}//4、打开并读取文件string filename = "mysql.jpg";//打开文件可以有多种方式,可以用c的file fopen,但是这个在vs2017里面说不安全,得设置不安全选项//fopen_s 是多线程安全版本的,到了linux又不行了//为了跨平台,用C++方式读取 fstream//需要知道文件大小和文件二进制  考虑到空间的分配和释放 动态空间//int filesize = 0;//ios::binary必须写,因为是二进制文件,如果是文本文件,无所谓不用加,但是还是加着fstream in(filename, ios::in | ios::binary);//文件是否存在if (!in.is_open()){cerr << "file" << filename << "open failed" << endl;}//fopen//句柄,文件指针移到结尾处//从结尾往前移动,移动0个位置,也就是结尾//判断位置in.seekg(0, ios::end);// 得到文件大小,//文件大小和文件二进制int filesize = in.tellg();//得到大小之后,将文件移到开头,要不然待会读文件就读不到了in.seekg(0, ios::beg);//分配空间大小char* data = new char[filesize];//查看是否读完,不保证一次读完,所以用循环读,可以直到读取了多少int readed = 0;//已经读了多少while (!in.eof()){//in.read(data, filesize); data读什么数据,filesize读多少//指针要进行移位in.read(data + readed, filesize - readed);//上次读了多少字节if (in.gcount()<=0){break;}readed += in.gcount();}in.close();//5、绑定字段MYSQL_BIND bind[3] = { 0 };bind[0].buffer_type = MYSQL_TYPE_STRING; //name文件名//(char*) buffer要求的是void*,而c_str()是只读的,所以要转换char*。//而bind是可以输入可以输出,所以不可以只读。默认const是只读的,但是在这儿是插入数据,不会修改数据,可以用char*bind[0].buffer = (char*)filename.c_str();//原图的文件名bind[0].buffer_length = filename.size();bind[1].buffer_type = MYSQL_TYPE_BLOB;// data 文件二进制内容bind[1].buffer = data; //二进制文件bind[1].buffer_length = filesize; //文件大小//把文件大小存下来//从mysql取出来,可以知道文件大小,但是不一定将它取出来,//经常做显示文件列表,有时候不需要显示二进制。希望有个字段将文件大小存下来bind[2].buffer_type = MYSQL_TYPE_LONG;//长整型,不用直到size,因为是固定大小bind[2].buffer = &filesize;  //存放指针//6、绑定if (mysql_stmt_bind_param(stmt, bind)!=0) //定义和文档不一致,=表示成功{//cerr错误输出,在重定向的时候,可以分割开来,也可以写到文件当中//cout 标准输出/*cout:写到标准输出的ostream对象;cerr:输出到标准错误的ostream对象,常用于程序错误信息;clog:也是输出标准错误流(这点儿和cerr是一样的),貌似平时很少用到这个啊;*/cerr << "mysql_stmt_bind_param failed" << mysql_stmt_error(stmt) << endl;}//7、执行stmt sqlif (mysql_stmt_execute(stmt) != 0){//cerr错误输出cerr << "mysql_stmt_execute failed" << mysql_stmt_error(stmt) << endl;}delete [] data;mysql_stmt_close(stmt);mysql_close(&mysql);mysql_library_end();system("pause");return 0;
}

插入成功

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/232508.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CSS3 边框border、outline、box-shadow

1 border 语法&#xff1a;border: width style color 2 outline 语法&#xff1a;outline: width style color 2.1 outline-offet MDN解释&#xff1a;用于设置outline与一个元素边缘或边框之间的间隙 即&#xff1a;设置outline相对border外边缘的偏移&#xff0c;可以为…

[足式机器人]Part2 Dr. CAN学习笔记-自动控制原理Ch1-9PID控制器

本文仅供学习使用 本文参考&#xff1a; B站&#xff1a;DR_CAN Dr. CAN学习笔记-自动控制原理Ch1-9PID控制器&#xff09; P —— Proportional I —— Integral D —— Derivative 当前误差/过去误差/误差的变化趋势 K p ⋅ e K_{\mathrm{p}}\cdot e Kp​⋅e&#xff1a;比…

弹性搜索引擎Elasticsearch:本地部署与远程访问指南

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言系统环境1. Windows 安装Elasticsearch2. 本地访问Elasticsearch3. Windows 安装…

[元带你学: eMMC协议 31] CRC 错误检测保证可靠性

依公知及经验整理,原创保护,禁止转载。 专栏 《元带你学: eMMC 协议》 <<<< 返回总目录 <<<< 前言 图片来源: www.elprocus.com 对于 eMMC 存储设备,CRC 校验在数据传输过程中起到了重要的作用。它能够检测出数据在存储和传输过程中的错误,确保…

手拉手springboot3整合mybatis-plus多数据源

环境介绍 技术栈 springbootmybatis-plusmysql 软件 版本 mysql 8 IDEA IntelliJ IDEA 2022.2.1 JDK 17 Spring Boot 3.1.7 dynamic-datasource 3.6.1 mybatis-plus 3.5.3.2 加入依赖 <dependency><groupId>com.baomidou</groupId><arti…

8 单链表---带表头节点

上节课所学的顺序表的缺点 顺序表的最大问题&#xff1a;插入和删除时需要移动大量元素 链式存储的定义 链式存储的逻辑结构 链表中的基本概念&#xff1a; 注意&#xff1a;表头节点并不属于数据元素 单链表图示&#xff1a; 把3个需要的结构体定义出来&#xff1a; typdef …

【数据结构】二叉树的概念及堆

前言 我们已经学过了顺序表、链表、栈和队列这些属于线性结构的数据结构&#xff0c;那么下面我们就要学习我们第一个非线性结构&#xff0c;非线性结构又有哪些值得我们使用的呢&#xff1f;那么接下来我们就将谈谈树的概念了。 1.树的概念与结构 1.1树的概念 树是一种非线性…

docker拉取镜像提示 remote trust data does not exist for xxxxxx

1、How can I be sure that I am pulling a trusted image from docker 2、docker: you are not authorized to perform this operation: server returned 401. 以上两个问题可以试试以下解决办法 DOCKER_CONTENT_TRUSTfalse 本人是使用jenkins部署自己的项目到docker容器出现…

MvvmToolkit的使用

背景&#xff1a;MvvmLight不更新了&#xff0c;用Toolkit代替 1、首先下载好社区版本的NuGet包 2、ViewModel中需要继承ObservableObject&#xff0c;查看ObservableObject可以看到里面有实现好InotifyPropertyChanged。 3、对于属性的set&#xff0c;可以简写成一行&#xff…

多线程高级知识点

多线程高级知识点 1.ThreadLocal 1.1 什么是 ThreadLocal&#xff1f; ​ ThreadLocal 叫做本地线程变量&#xff0c;意思是说&#xff0c;ThreadLocal 中填充的的是当前线程的变量&#xff0c;该变量对其他线程而言是封闭且隔离的&#xff0c;ThreadLocal 为变量在每个线程…

qt三大控件

1.QListWidget控件 先在ui界面将 QListWidget拖出来竖直对齐 再去代码中实现文本插入 两种插入方式 方法1 //listWidget使用 有左右中间对齐需求QListWidgetItem * itemnew QListWidgetItem("床前明月光"); // //上面只是独立的一句话,没有关联起来ui-&g…

6.OpenResty系列之深入理解(二)

1. 日志输出 vim /usr/local/openresty/nginx/conf/nginx.conf默认配置如下 #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info;#pid logs/nginx.pid;http {#log_format main $remote_addr - $remote_user [$time…

计算机Java项目|基于Springboot实现患者管理系统

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 文末获取源码 项目编号&#xff1a;KS-032…

LeCode:(606. 根据二叉树创建字符串)

题目链接 本体的难点&#xff1a; 什么时候去打印左右括号&#xff1f;什么时候省略&#xff1f; 解题过程&#xff1a;通过观察看到&#xff0c;每次遍历结点之前&#xff0c;打印了一个左括号&#xff1b;遍历到叶子&#xff0c;叶子的左右也要打印出括号来&#xff08;先…

在VM下使用Composer完成快照方式的软件制作

Composer允许您构建软件、应用程序、偏好设置文件或是文档的安装包&#xff0c;安装包可以部署到远程电脑或是作为镜像流程的一部分。构建软件包的第一步就是创建包源&#xff0c;根据要打包的软件&#xff0c;Composer允许您监视软件的安装和使用驱动器上已存在的文件来创建包…

ansible 配置jspgou商城上线(MySQL版)

准备环境 准备两台纯净的服务器进行&#xff0c;在实验之前我们关闭防火墙和selinux systemctl stop firewalld #关闭防火墙 setenforce 0 #临时关闭selinux hosts解析(两台服务器都要去做) [rootansible-server ~]# vim /etc/hosts 10.31.162.24 ansible-ser…

性能优化-OpenMP基础教程(五)-全面讲解OpenMP基本编程方法

本文主要介绍OpenMP编程的编程要素和实战&#xff0c;包括并行域管理详细实战、任务分担详细实战。 &#x1f3ac;个人简介&#xff1a;一个全栈工程师的升级之路&#xff01; &#x1f4cb;个人专栏&#xff1a;高性能&#xff08;HPC&#xff09;开发基础教程 &#x1f380;C…

【数据仓库与联机分析处理】多维数据模型

目录 一、数据立方体 二、数据模型 &#xff08;一&#xff09;星形模型 &#xff08;二&#xff09;雪花模式 &#xff08;三&#xff09;事实星座模式 三、多维数据模型中的OLAP操作 &#xff08;一&#xff09;下钻 &#xff08;二&#xff09;上卷 &#xff08;三…

React之useRef hook

介绍 useRef是react的自定义hook&#xff0c;它用来引用一个不需要渲染的值。这篇文章会介绍useRef的简单用法。 使用场景 1.实现节流 通过useRef实现节流功能&#xff0c;在限制时间内多次提交&#xff0c;已第一次提交为准。 useThrottle.jsx import {useEffect, useRef,…

矩阵的乘法

首先矩阵的乘法定义如下&#xff1a; #include <stdio.h> int main() { int i 0; int j 0; int arr[20][20] { 0 }; int str[20][20] { 0 }; int s[20][20] { 0 }; int n1 0; int n2 0; int m2 0; int z 0; int m1 0;…