MySQL存储图片读取图片

 注意!!!

图片是否能够显示完全有一个注意点 数据表中的BLOB类型设置是否够大

1、MySQL有四种BLOB类型:   ·

        tinyblob:仅255个字符   

        blob:最大限制到65K字节   

        mediumblob:限制到16M字节   

        longblob:可达4GB

2、除了类型对后面存取文件大小有限制,还要修改mysql的配置文件。   

        Windows、linux基本一样通过修改文件my.ini或my.cnf文件,在文件中增加 max_allowed_packet=10M(就是最大10M,mysql默认似乎1MB,增加前先查找一下确保没有设置过)

3、做了以上设置后,如果上传较大一点文件时或者某些文件时还是出错,如报一些乱码,估计就是下面的问题了。 数据库或表的字符集问题,如hibernate连接使用utf-8,表是gbk等,一般只要设置hibernate中数据连接部分就行,如 jdbc:mysql://192.168.0.4:3306/test?useUnicode=true&characterEncoding=UTF-8

读写流程图
读写流程图
 如何从磁盘中读取图片数据
//从选取的文件中读取图片数据
int ReadImg(char *filename ,char *buffer) //filename:用来存储 Path+filename buffer:用来存储
{
	if (NULL == filename || buffer == NULL)
	{
		return -1;
	}

	//打开文件
	FILE* fp = fopen(filename, "rb");//rb 以读的方式打开

	//判断是否成功打开了文件
	if (NULL == fp )
	{
		printf("Fopen fail! \n");
		return -2;
	}

	//测量文件字节数(偏移量  三板斧 都得要
	fseek(fp, 0, SEEK_END);将位置指针移动到文件末尾

	int length = ftell(fp); // file size 确定文件的大小

	fseek(fp, 0, SEEK_SET);//将位置指针移动到文件开头

	int size = fread(buffer, 1,length,fp); //每次读取一个字节	从fp的指向开始 每次读1个字节 存放到buffer中 要执行length次

	//判断两者长度是否一致 也就是读出来的数据大小是否等于文件大小
	if (size != length)
	{
		printf("FileRead error!%d \n",size);
		return -3;
	}

	//关闭文件
	fclose(fp);
}
如何把数据库中的图片数据存放到文件中
//将图片数据写入磁盘
int WirteImg(char* filename, char* buffer, int length)  //写到哪个文件中 写入的数据是哪些 写入的长度是多少
{
	if (filename == NULL || buffer == NULL || length <= 0) return -1;

	FILE* fp = fopen(filename,"wb"); //wb 以写的方式打开

	//判断是否成功打开了文件
	if (NULL == fp)
	{
		printf("Fopen fail! \n");
		return -2;
	}

	int size = fwrite(buffer, 1, length, fp);//每次读取一个字节 从fp的指向存放 每次读1个字节 要执行length次
	
	//判断两者长度是否一致 也就是读出来的数据大小是否等于文件大小
	if (size != length)
	{
		printf("FileWrite error!%d \n", size);
		return -3;
	}
	fclose(fp);

}

在表中增加一行为我们的图片存储做准备\

alter table TB_USER ADD UIMG BLOB;
MySQL写入数据
//数据库中存储图片数据
int MySQL_WriteImg(MYSQL *mysql,char *buffer, int length)
{
	if (mysql == NULL || buffer == NULL || length <= 0) return -1;

	MYSQL_STMT* stmt = mysql_stmt_init(mysql);//初始化数据缓存

		int ret = mysql_stmt_prepare(stmt, SQL_INSERT_TB_USER_IMG, strlen(SQL_INSERT_TB_USER_IMG));
		if (ret)
		{
		printf("mysql_stmt_prepare is error ! %s \n",mysql_error(mysql));
		return -2;
	    }
	
    //绑定数据
	MYSQL_BIND parme = { 0 }; //用于语句输入和返回值 通常和stmt绑定使用
	parme.buffer_type = MYSQL_TYPE_LONG_BLOB;
	parme.buffer = NULL;
	parme.is_null = 0;
	parme.length = NULL;

	ret = mysql_stmt_bind_param(stmt,&parme);

	if (ret) 
	{
		printf("mysql_stmt_bind_param is error ! %s \n", mysql_error(mysql));
		return -3;
	}

	//发送数据到数据库服务器中
	ret = mysql_stmt_send_long_data(stmt, 0, buffer, length);
	if (ret)
	{
		printf("mysql_stmt_send_long_data is error ! %s \n", mysql_error(mysql));
		return -4;
	}

	//存储到表中
	ret = mysql_stmt_execute(stmt);
	if (ret)
	{
		printf("mysql_stmt_execute is error ! %s \n", mysql_error(mysql));
		return -5;
	}

    //以上执行完毕关闭stmt
	ret = mysql_stmt_close(stmt);
	if (ret)
	{
		printf("mysql_stmt_close is error ! %s \n", mysql_error(mysql));
		return -6;
	}

	return ret;
}
MySQL读取数据
//从数据库中读取图片资源写入到磁盘
int MySQL_ReadImg(MYSQL *mysql,char * buffer, int length)
{
	if (mysql == NULL || buffer == NULL || length <= 0) return -1;

	MYSQL_STMT* stmt = mysql_stmt_init(mysql);//初始化数据缓存

	//执行语句拿到返回值存储到stmt
	int ret = mysql_stmt_prepare(stmt, SQL_SELECT_TB_USER_IMG, strlen(SQL_SELECT_TB_USER_IMG));

	if (ret)
	{
		printf("mysql_stmt_prepare is error ! %s \n", mysql_error(mysql));
		return -2;
	}


	//以下都是数据处理
	//绑定结果
	MYSQL_BIND result = { 0 }; //用于语句输入和返回值 通常和stmt绑定使用
	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 is error ! %s \n", mysql_error(mysql));
		return -3;
	}

	//执行语句
	ret = mysql_stmt_execute(stmt);
	if (ret)
	{
		printf("mysql_stmt_execute is error ! %s \n", mysql_error(mysql));
		return -4;
	}

	//返回结果
	ret = mysql_stmt_store_result(stmt);
	if (ret) {
		printf("mysql_stmt_store_result : %s\n", mysql_error(mysql));
		return -5;
	}

	//数据显示 取出单行可以不需要外循环
	while (1) 
	{
		//mysql_stmt_fetch 抓取返回的数据集:stmt 的下一行数据
		ret = mysql_stmt_fetch(stmt);

		if (ret != 0 && ret != MYSQL_DATA_TRUNCATED) break; // MYSQL_DATA_TRUNCATED 出现数据截短 块存储分片 \
															   当mysql_stmt_fetch返回0时意味着数据读取完毕

		int start = 0;
		while (start<(int)total_length)
		{
			result.buffer = buffer + start;  //result.buffer和传入的参数buffer使用的是一个内存空间
			result.buffer_length = 1;        //buffer_length buffer的实际大小也就是每次接受数据的最大长度
			mysql_stmt_fetch_column(stmt, &result, 0, start);//mysql_stmt_fetch_column:当前行获取一列数据 s 
			                                                 //stmt:存储结果; 
			                                                 //result:保存返回数据的缓存空间;
															 //0:因为我们查询的数据列只有一个所以是第0个写0
															 //start:从什么位置开始的偏移量

			start += result.buffer_length;    //获取下一个偏移量 也就是当前start代表的偏移量+buffer_length的长度
		}

	}

	//关闭stmt
	mysql_stmt_close(stmt);

	//返回 数据总长
	return total_length;
}

本文全部代码如下:

#include <stdio.h>
#include <mysql.h>
#include <string.h>


//C U R D
//创建  更新  读取  删除

#define yang_db_server_ip			"192.168.126.132"   //数据库IP
#define yang_db_server_port         3306              //数据库链接的端口号

#define yang_db_server_definedb    "yang_db"  //该用户默认链接的数据库
#define yang_db_server_username     "admin"   //用户名
#define yang_db_server_password     "123456"  //密码

#define SQL_INSERT_TB_USER          "insert TB_USER(UNAME,USEX) value('sunyu','woman');"  //增加语句
#define SQL_INSERT_TB_USER_IMG      "insert TB_USER(UNAME,USEX,UIMG) value('12345','woman',?);"  //增加语句  在宏定义中?代表占位符因为不知道图片的内容所以使用?

#define SQL_SELECT_TB_USER			"SELECT * FROM TB_USER;"  //查询语句
#define SQL_SELECT_TB_USER_IMG		"SELECT UIMG FROM TB_USER WHERE UNAME = '12345';"  //查询语句


#define SQL_CALL_PROC_TB_USER	    "CALL PROC_DELETE_TBUSER('sun');"  //调用删除的存储过程

#define FILE_IMAGE_LENGTH			(1536*1824) //文件大小

int sel(MYSQL* sqldata)
{
	//第一步
	if (mysql_real_query(sqldata, SQL_SELECT_TB_USER, strlen(SQL_SELECT_TB_USER)))
	{
		printf("SQL_SELECT :%s \n ", mysql_error(sqldata));
	}
	//第二步
	MYSQL_RES* res = mysql_store_result(sqldata);保存返回语句的内容
	if (res == NULL)
	{
		printf("mysql_store_result: %s \n", mysql_error(sqldata));
		return -2;
	}
	//第三步 判断数据集合的行数
	int rows = mysql_num_rows(res);
	printf("Rows :%d \n", rows);

	//列数
	int cows = mysql_num_fields(res);
	printf("Cows :%d \n", cows);


	//第四步 将返回的数据逐行取出
	MYSQL_ROW row; //row是一个存放数据的数组类似于C#中的sqlread函数
	while ((row = mysql_fetch_row(res)))  //判断行是否为空
	{
		int i = 0;
		for (i = 0; i < cows; i++)
		{
			printf("%s \t", row[i]);
		}
		printf("\n");
	}

	mysql_free_result(res);
	return 0;
	//goto Exit;
}

//从选取的文件中读取图片数据
int ReadImg(char *filename ,char *buffer) //filename:用来存储 Path+filename buffer:用来存储
{
	if (NULL == filename || buffer == NULL)
	{
		return -1;
	}

	//打开文件
	FILE* fp = fopen(filename, "rb");//rb 以读的方式打开

	//判断是否成功打开了文件
	if (NULL == fp )
	{
		printf("Fopen fail! \n");
		return -2;
	}

	//测量文件字节数(偏移量  三板斧 都得要
	fseek(fp, 0, SEEK_END);将位置指针移动到文件末尾

	int length = ftell(fp); // file size 确定文件的大小

	fseek(fp, 0, SEEK_SET);//将位置指针移动到文件开头

	int size = fread(buffer, 1,length,fp); //每次读取一个字节	从fp的指向开始 每次读1个字节 存放到buffer中 要执行length次

	//判断两者长度是否一致 也就是读出来的数据大小是否等于文件大小
	if (size != length)
	{
		printf("FileRead error ! %d \n",size);
		return -3;
	}

	//关闭文件
	fclose(fp);

	//返回长度
	return size;
}

//数据库中存储图片数据
int MySQL_WriteImg(MYSQL *mysql,char *buffer, int length)
{
	if (mysql == NULL || buffer == NULL || length <= 0) return -1;

	MYSQL_STMT* stmt = mysql_stmt_init(mysql);//初始化数据缓存

		int ret = mysql_stmt_prepare(stmt, SQL_INSERT_TB_USER_IMG, strlen(SQL_INSERT_TB_USER_IMG));
		if (ret)
		{
		printf("mysql_stmt_prepare is error ! %s \n",mysql_error(mysql));
		return -2;
	    }
	
    //绑定数据
	MYSQL_BIND parme = { 0 }; //用于语句输入和返回值 通常和stmt绑定使用
	parme.buffer_type = MYSQL_TYPE_LONG_BLOB;
	parme.buffer = NULL;
	parme.is_null = 0;
	parme.length = NULL;

	ret = mysql_stmt_bind_param(stmt,&parme);

	if (ret) 
	{
		printf("mysql_stmt_bind_param is error ! %s \n", mysql_error(mysql));
		return -3;
	}

	//发送数据到数据库服务器中
	ret = mysql_stmt_send_long_data(stmt, 0, buffer, length);
	if (ret)
	{
		printf("mysql_stmt_send_long_data is error ! %s \n", mysql_error(mysql));
		return -4;
	}

	//存储到表中
	ret = mysql_stmt_execute(stmt);
	if (ret)
	{
		printf("mysql_stmt_execute is error ! %s \n", mysql_error(mysql));
		return -5;
	}

    //以上执行完毕关闭stmt
	ret = mysql_stmt_close(stmt);
	if (ret)
	{
		printf("mysql_stmt_close is error ! %s \n", mysql_error(mysql));
		return -6;
	}

	return ret;
}

//从数据库中读取图片资源写入到磁盘
int MySQL_ReadImg(MYSQL *mysql,char * buffer, int length)
{
	if (mysql == NULL || buffer == NULL || length <= 0) return -1;

	MYSQL_STMT* stmt = mysql_stmt_init(mysql);//初始化数据缓存

	//执行语句拿到返回值存储到stmt
	int ret = mysql_stmt_prepare(stmt, SQL_SELECT_TB_USER_IMG, strlen(SQL_SELECT_TB_USER_IMG));

	if (ret)
	{
		printf("mysql_stmt_prepare is error ! %s \n", mysql_error(mysql));
		return -2;
	}


	//以下都是数据处理
	//绑定结果
	MYSQL_BIND result = { 0 }; //用于语句输入和返回值 通常和stmt绑定使用
	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 is error ! %s \n", mysql_error(mysql));
		return -3;
	}

	//执行语句
	ret = mysql_stmt_execute(stmt);
	if (ret)
	{
		printf("mysql_stmt_execute is error ! %s \n", mysql_error(mysql));
		return -4;
	}

	//返回结果
	ret = mysql_stmt_store_result(stmt);
	if (ret) {
		printf("mysql_stmt_store_result : %s\n", mysql_error(mysql));
		return -5;
	}

	//数据显示 取出单行可以不需要外循环
	while (1) 
	{
		//mysql_stmt_fetch 抓取返回的数据集:stmt 的下一行数据
		ret = mysql_stmt_fetch(stmt);

		if (ret != 0 && ret != MYSQL_DATA_TRUNCATED) break; // MYSQL_DATA_TRUNCATED 出现数据截短 块存储分片 \
															   当mysql_stmt_fetch返回0时意味着数据读取完毕

		int start = 0;
		while (start<(int)total_length)
		{
			result.buffer = buffer + start;  //result.buffer和传入的参数buffer使用的是一个内存空间
			result.buffer_length = 1;        //buffer_length buffer的实际大小也就是每次接受数据的最大长度
			mysql_stmt_fetch_column(stmt, &result, 0, start);//mysql_stmt_fetch_column:当前行获取一列数据 s 
			                                                 //stmt:存储结果; 
			                                                 //result:保存返回数据的缓存空间;
															 //0:因为我们查询的数据列只有一个所以是第0个写0
															 //start:从什么位置开始的偏移量

			start += result.buffer_length;    //获取下一个偏移量 也就是当前start代表的偏移量+buffer_length的长度
		}

	}

	//关闭stmt
	mysql_stmt_close(stmt);

	//返回 数据总长
	return total_length;
}

//将图片数据写入磁盘
int WirteImg(char* filename, char* buffer, int length)  //写到哪个文件中 写入的数据是哪些 写入的长度是多少
{
	if (filename == NULL || buffer == NULL || length <= 0) return -1;

	FILE* fp = fopen(filename,"wb"); //wb 以写的方式打开

	//判断是否成功打开了文件
	if (NULL == fp)
	{
		printf("Fopen fail! \n");
		return -2;
	}

	int size = fwrite(buffer, 1, length, fp);//每次读取一个字节 从fp的指向存放 每次读1个字节 要执行length次
	
	//判断两者长度是否一致 也就是读出来的数据大小是否等于文件大小
	if (size != length)
	{
		printf("FileWrite error!%d \n", size);
		return -3;
	}
	fclose(fp);

}

int main()
{
	//注:mysql的两个接口以返回0作为失败
	MYSQL mysql;

	if (NULL == mysql_init(&mysql))   //初始化数据库
	{
		printf("mysql_init :%s \n", mysql_error(&mysql)); //mysql提供了统一的错误值
		return -1;
	}

	//mysql_real_connect返回非0成功
	if (!mysql_real_connect(&mysql, yang_db_server_ip,
		yang_db_server_username, yang_db_server_password,
		yang_db_server_definedb, yang_db_server_port, NULL, 0))//第一个参数是定义的数据库对象 第二个是IP地址 三四是用户名和密码 第五个是默认链接数据库名 第六个是端口号 七八置空
	{
		printf("mysql_real_connect:%s \n", mysql_error(&mysql));
		goto Exit;
	}

#if 1
	sel(&mysql);
#endif 

//读取磁盘的图片资源写入到mysql服务器中
#if 1
	printf("case : mysql --> read image and write mysql\n");

	char buffer[FILE_IMAGE_LENGTH] = { 0 };
	int length = ReadImg("1.jpg", buffer); //图片和代码不在一个文件下用绝对路径,在可以直接写文件名
	if (length < 0)
	{
		printf("length : %d \n", length);
		goto Exit;
	}
	printf("length : %d \n", length);
	MySQL_WriteImg(&mysql, buffer, length);

#endif // 1

//读取数据库中的图片资源并写入磁盘
#if 1
	printf("case : mysql --> read mysql and write image\n");
	char buffers[FILE_IMAGE_LENGTH] = { 0 };
	memset(buffers, 0, FILE_IMAGE_LENGTH);

    int len = MySQL_ReadImg(&mysql, buffers, FILE_IMAGE_LENGTH);

	WirteImg("a.jpg", buffers,len);

#endif
#if 0
	//insert----SQL
	//mysql_real_query返回0成功
	if (mysql_real_query(&mysql, SQL_INSERT_TB_USER, strlen(SQL_INSERT_TB_USER)))
	{
		printf("mysql_real_query :%s \n ", mysql_error(&mysql));
		goto Exit;
	}
#endif

#if 0
	printf("case : mysql --> delete \n");
	//delete----SQL
	//mysql_real_query返回0成功
	if (mysql_real_query(&mysql, SQL_CALL_PROC_TB_USER, strlen(SQL_CALL_PROC_TB_USER)))
	{
		printf("mysql_real_query :%s \n ", mysql_error(&mysql));
		goto Exit;
	}
#endif

#if 1
	sel(&mysql);
#endif
Exit:
	mysql_close(&mysql);

	return 0;
}

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值