SQLite的BLOB数据类型与C++二进制存储学习记录

news2024/11/22 20:26:54

一、BLOB数据类型简介

        Blob(Binary Large Object)是一种用于存储二进制数据的数据类型,在数据库中常用于存储图片、音频和视频等大型(大数据量)的二进制数据[1-2]。需要注意的是,SQLite中BLOB类型的单对象最大存储字节数由预处理器宏SQLITE_MAX_LENGTH定义并可以提高或降低该值,但是当前的实现只支持最大长度为2^{31}-1字节。

        在SQLite的部分INSERT和SELECT语句处理过程中,数据库中每一行的完整内容被编码为单个BLOB数据类型对象,所以SQLITE_MAX_LENGTH宏定义决定了数据库中一行的最大字节数[3]

二、C++标准库之bitset简介[4-6]

       C++标准库中的bitset库,是一个模板类(模板参数定义了位集合的大小)且提供了一种方式来操作固定大小的位集合。位集合是一个由位(bit)组成的数组,每个位可以是0或1,因此bitset类型非常适合于需要表示二进制数据或进行位操作的场景。

        位运算的优势在于可以大量减少运行开销,优化算法。其运算速度快的原因是直接使用计算机底层的二进制机器操作指令。较为详细的位运算理论理解与实际用例可参考资料[6]。

二、C++中基本数据类型实例与其二进制存储形式探索[7-10]

        计算机中的所有数据,无论是文本、图像、音频还是视频,最终都会被转换为二进制形式进行存储和处理。比特/位(bit)是计算机内存中的最小/原子单位,也是数据传输的最小单位;字节(Byte)是计算机系统中最小的存储单位,是计算机记忆体(memory)存储资料的基本单位,每个字节由八个比特位组成。

       C++基本内置数据类型在计算机内部存储数据时使用二进制,但在向用户显示时使用八进制、十进制与十六进制等进制。需要注意的是,整数类型是按照二进制补码的方式来存储数值(非负整数直接使用二进制表示,无符号位),其最高位(最左边一位)用于表示符号(0表示正数,1表示负数),剩下的位数表示数值部分;浮点数类型是按照IEEE 754标准来存储数据,然后根据浮点数数值转换公式进行数值计算。详细叙述可参考资料[7]。

        计算机中的字符按照字符集编码表示,常见的字符集编码有ASCII编码、ANSI编码、Unicode编码以及UTF-8编码。其中,ASCII码(American Standard Code for Information Interchange,美国信息交换标准码),一个英文字母(不分大小写)占一个字节的空间。ASCII码字符代码表可参考资料[10]。

        (一)实验一 基于字符串的逐字符二进制编码转换

        (二)实验二 长整型向量的逐一元素二进制编码转换

        (三)实验三 字符型向量的逐一元素二进制编码转换

实验总结:

1. C++基本内置数据类型在计算机内部存储数据时使用二进制;

2. 基于标准库bitset可以将存储数据以二进制的形式显化展示;

3. 字符类型(char)占一个字节,其不仅可以基于ASCII码存储字符,还可以在单字节限制下存储有限大小的整型数据(实质上,char与int之间存在隐式转换)。

三、基于SQLite实现图像数据库管理(图像的存取实例)[11-12]

        该示例代码仅实现了图像数据的数据库/表创建及数据插入,未实现数据库图像的读取与二进制码解析。数据库图像的读取与二进制码解析概要代码可参考资料[12]。

#include <iostream>
#include <string>
#include <vector>
#include "opencv2/opencv.hpp"
#include "sqlite3.h"

using namespace std;

// 实验数据
string imagePath = "./icon.jpg";

int main()
{
	// 读取图像文件并检查图像是否读取成功
	cv::Mat image = cv::imread(imagePath);
	if (image.empty()) {
		cout << "无法读取图像文件。" << endl;
		return -1;
	}
	// 创建图像存储表
	/*
		图像存储表设计(该表包含"id"、"name"、"size"、"type"、"data"五个字段):
		1. "id"字段作为主键,自动递增;
		2. "name"字段用于存储图像的名称;
		3. "size"字段用于存储图像的大小(以字节为单位);
		4. "type"用于存储图像的类型(如.jpg和.png等);
		5. "data"字段为BLOB类型,用于存储图像的二进制类型
	*/
	sqlite3* db;
	int rc = sqlite3_open("./imageDB.db", &db);
	if (rc)
	{
		std::cerr << "无法打开数据库: " << sqlite3_errmsg(db) << std::endl;
		return 1;
	}
	else
	{
		std::cout << "数据库打开成功" << std::endl;
	}
	// 创建数据库表
	char* errMsg = 0;
	const char* sql = "CREATE TABLE IF NOT EXISTS images"
					  "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
		              "name TEXT NOT NULL,"
					  "size INTEGER NOT NULL,"
					  "type TEXT NOT NULL,"
		              "data BLOB);";
	rc = sqlite3_exec(db, sql, 0, 0, &errMsg);
	if (rc != SQLITE_OK)
	{
		std::cerr << "SQL错误: " << errMsg << std::endl;
		sqlite3_free(errMsg);
		sqlite3_close(db);
		return -1;
	}
	else
	{
		std::cout << "表创建成功" << std::endl;
	}
	// 处理图像数据(将图像数据转换为二进制数据)
	vector<uchar> buffer;
	cv::imencode(".jpg", image, buffer);  // 该函数将图像以设定图片格式编码存储到buffer
								          // 该函数将图像数据编码转换为指定格式的字节流,这个字节流本质上就是二进制数据
	size_t size = sizeof(buffer);
	uchar* dataPtr = buffer.data();
	// 基于参数化方式将图像数据存入表
	/*
		参数化方式的原理:
		参数化将SQL语句的结构与数据分开。SQL语句中的参数位置用?占位符表示,
		然后通过专门的绑定函数将实际数据绑定到这些占位符上。
		参数化方式的优势:
		这样可以有效避免SQL注入攻击。
		因为SQL语句的语法结构是固定的,用户输入的数据不会被解释为SQL语法的一部分
	*/
	const char* sql1 = "INSERT INTO images (id,name,size,type,data)"
		               "VALUES (?, ?, ?, ?, ?);";
	sqlite3_stmt* stmt;
	int rc1 = sqlite3_prepare_v2(db, sql1, -1, &stmt, nullptr);
	if (rc1 != SQLITE_OK) {
		std::cerr << "准备插入语句出错: " << sqlite3_errmsg(db) << std::endl;
		sqlite3_close(db);
		return -1;
	}
	sqlite3_bind_int(stmt, 1, 0);
	sqlite3_bind_text(stmt, 2, "icon", -1, SQLITE_TRANSIENT);
	sqlite3_bind_int(stmt, 3, size);
	sqlite3_bind_text(stmt, 4, "jpg", -1, SQLITE_TRANSIENT);
	sqlite3_bind_blob(stmt, 5, dataPtr, -1, SQLITE_TRANSIENT);
	int rc2 = sqlite3_step(stmt);
	if (rc2 != SQLITE_DONE) {
		std::cerr << "执行插入语句出错: " << sqlite3_errmsg(db) << std::endl;
	}
	cout << "图像数据插入成功" << endl;
	sqlite3_finalize(stmt);
	return 0;
}

参考资料:

[1] Datatypes In SQLite

[2] SQLite Blob 数据类型详解|极客笔记 (deepinout.com)

[3] SQLite 的实现限制 | SQLite中文网 (readdevdocs.com)

[4] C++ 数据类型 | 菜鸟教程 (runoob.com)

[5] C++之std::bitset使用精讲(全)-CSDN博客

[6] 位运算的运用场景使用总结_位运算的使用场景-CSDN博客

[7] C++内置数据类型与二进制存储 | 我有昕想法 | Peter_Matthew的博客 (zhangkai.xin)

[8] 计算机科学导论:第三章 数据存储 - 知乎 (zhihu.com)

[9] 在 C++ 中将字符串转换为二进制序列 | D栈 - Delft Stack

[10] ASCII 表 | 菜鸟教程 (runoob.com)

[11] SQLite 数据库中插入和读取 BLOB 数据|极客笔记 (deepinout.com)

[12] SQLite 如何在SQLite数据库中存储图像|极客教程

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C# 自己编写web服务

文件后缀响应 "text/html"; 文件后缀响应 "application/json"; httpListenerContext.Response.ContentType 文件后缀响应; httpListenerContext.Response.AppendHeader("Access-Control-Allow-Origin", "*"); // L…

微服务day04

网关 网关路由 快速入门 创建新模块&#xff1a;hm-gateway继承hmall父项目。 引入依赖&#xff1a;引入网关依赖和nacos负载均衡的依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"…

Agent框架调研:19种Agent架构对比分析

代理&#xff08;Agent&#xff09;指能自主感知环境并采取行动实现目标的智能体&#xff0c;即AI作为一个人或一个组织的代表&#xff0c;进行某种特定行为和交易&#xff0c;降低一个人或组织的工作复杂程度&#xff0c;减少工作量和沟通成本。 背景 目前&#xff0c;我们在…

ODOO学习笔记(4):Odoo与SAP的主要区别是什么?

Odoo 和 SAP 都是知名的企业资源规划&#xff08;ERP&#xff09;软件&#xff0c;它们之间存在以下一些主要区别&#xff1a; Odoo与SAP的区别 一、功能特点 功能广度 Odoo&#xff1a;提供了一整套全面的业务应用程序&#xff0c;涵盖了销售、采购、库存管理、生产、会计、…

python之正则表达式总结

正则表达式 对于正则表达式的学习&#xff0c;我整理了网上的一些资料&#xff0c;希望可以帮助到各位&#xff01;&#xff01;&#xff01; 我们可以使用正则表达式来定义字符串的匹配模式&#xff0c;即如何检查一个字符串是否有跟某种模式匹配的部分或者从一个字符串中将与…

【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板

文章目录 一、日志框架介绍1、浅谈与slfj4、log4j、logback的关系2、性能方面3、Slf4j使用方法 二、log4j配置三、log4j2配置1、SpringBoot整合Log4j22、非SpringBoot项目引入的依赖3、log4j2-spring.xml文件&#xff08;Spring项目&#xff09;或log4j2.xml&#xff08;非Spri…

StarUML建模工具安装学习与汉化最新零基础详细教程【一键式下载】(适用于Windows、MacOS系统、Linux系统)

StarUML破解安装下载教程 前言&#xff1a; StarUML破解与汉化安装下载教程&#xff0c;仅供学习研究和交流使用&#xff0c;禁止作为商业用途或其他非法用途&#xff01; 仓库作者&#xff1a;X1a0He&#xff0c;经仓库作者授权使用。 目录 StarUML破解安装下载教程1. 下载…

【网络安全】2.3 安全的网络设计_2.防御深度原则

文章目录 一、网络架构二、网络设备三、网络策略四、处理网络安全事件五、实例学习&#xff1a;安全的网络设计结论 网络设计是网络安全的基础&#xff0c;一个好的网络设计可以有效的防止攻击者的入侵。在本篇文章中&#xff0c;我们将详细介绍如何设计一个安全的网络&#…

IoTDB 与 HBase 对比详解:架构、功能与性能

五大方向&#xff0c;洞悉 IoTDB 与 HBase 的详尽对比&#xff01; 在物联网&#xff08;IoT&#xff09;领域&#xff0c;数据的采集、存储和分析是确保系统高效运行和决策准确的重要环节。随着物联网设备数量的增加和数据量的爆炸式增长&#xff0c;开发者和决策者们需要选择…

如何找到系统中bert-base-uncased默认安装位置

问题&#xff1a; 服务器中无法连接huggingface&#xff0c;故需要自己将模型文件上传 ubuntu 可以按照这个链接下载 Bert下载和使用&#xff08;以bert-base-uncased为例&#xff09; - 会自愈的哈士奇 - 博客园 里面提供了giehub里面的链接 GitHub - google-research/be…

Qt 学习第十六天:文件和事件

一、创建widget对象&#xff08;文件&#xff09; 二、设计ui界面 放一个label标签上去&#xff0c;设置成box就可以显示边框了 三、新建Mylabel类 四、提升ui界面的label标签为Mylabel 五、修改mylabel.h&#xff0c;mylabel.cpp #ifndef MYLABEL_H #define MYLABEL_H#incl…

华为ensp配置bgp(避坑版)

文章目录 前言一、BGP是什么&#xff1f;二、拓扑三、基础配置四、测试五、拓展总结 前言 BGP&#xff08;Border Gateway Protocol&#xff0c;边界网关协议&#xff09;是一种在互联网中使用的路径矢量协议。它主要用于在不同的自治系统&#xff08;AS&#xff09;之间交换路…

QT最新版6.8在线社区版安装教程

访问QT的官网&#xff1a; Qt | Tools for Each Stage of Software Development Lifecycle 点击 Download Try&#xff1a; 点击社区版最新在线安装&#xff1a; 往下翻网页&#xff0c; 点击下载&#xff1a; 开始安装&#xff1a; 使用--mirror进行启动安装程序&#xff1…

鸿蒙多线程开发——Worker多线程

1、概 述 1.1、基本介绍 Worker主要作用是为应用程序提供一个多线程的运行环境&#xff0c;可满足应用程序在执行过程中与主线程分离&#xff0c;在后台线程中运行一个脚本进行耗时操作&#xff0c;极大避免类似于计算密集型或高延迟的任务阻塞主线程的运行。 创建Worker的线…

海量数据迁移:Elasticsearch到OpenSearch的无缝迁移策略与实践

文章目录 一&#xff0e;迁移背景二&#xff0e;迁移分析三&#xff0e;方案制定3.1 使用工具迁移3.2 脚本迁移 四&#xff0e;方案建议 一&#xff0e;迁移背景 目前有两个es集群&#xff0c;版本为5.2.2和7.16.0&#xff0c;总数据量为700T。迁移过程需要不停服务迁移&#…

在配置环境变量之后使用Maven报错 : mvn : 无法将“mvn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。

最近&#xff0c;我在 Windows 系统上安装和配置 Apache Maven 时遇到了一些问题&#xff0c;想在此记录下我的解决历程&#xff0c;希望对遇到类似问题的朋友有所帮助。 问题描述 我下载了 Maven 并按照常规步骤配置了相关的环境变量。然而&#xff0c;在 PowerShell 中输入…

大模型,智能家居的春秋战国之交

智能家居&#xff0c;大家都不陌生。尽管苹果、谷歌、亚马逊等AI科技巨头&#xff0c;以及传统家电厂商都在积极进入这一领域&#xff0c;但发展了十多年之后&#xff0c;智能家居依然长期呈现出一种技术上人工智障、市场上四分五裂的局面。 究其原因&#xff0c;是此前传统家电…

【设计模式】结构型模式(四):组合模式、享元模式

《设计模式之结构型模式》系列&#xff0c;共包含以下文章&#xff1a; 结构型模式&#xff08;一&#xff09;&#xff1a;适配器模式、装饰器模式结构型模式&#xff08;二&#xff09;&#xff1a;代理模式结构型模式&#xff08;三&#xff09;&#xff1a;桥接模式、外观…

众测遇到的一些案列漏洞

文章中涉及的敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打码处理。传播、利用本文章所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任,一旦造成后果请自行…

算法求解(C#)-- 寻找包含目标字符串的最短子串算法

1. 引言 在字符串处理中&#xff0c;我们经常需要从一个较长的字符串中找到包含特定目标字符串的最短子串。这个问题在文本搜索、基因序列分析等领域有着广泛的应用。本文将介绍一种高效的算法来解决这个问题。 2. 问题描述 给定一个源字符串 source 和一个目标字符串 targe…