当前位置: 首页 > news >正文

19.4.6 读写数据库中的二进制数据

版权声明:本文为博主原创文章,转载请在显著位置标明本文出处以及作者网名,未经作者允许不得用于商业目的。

需要北风数据库的请留言自己的信箱。

北风数据库中,类别表的图片字段在【数据表视图】中显示为Bitmap Image:

图19-30 图片字段的数据显示为Bitmap Image

它是一个OLE对象,实际就是一个字节数组:

图19-30 图片字段在设计视图中为OLE对象

双击某一个类别的Bitmap Image 可以打开画图查看图片:

图19-32 双击默认会使用画图打开

对于Access数据库中保存的二进制数据,应该使用OleDbCommand的ExecuteReader方法加参数SequentialAccess来打开获得对应的OleDbDataReader对象。

SequentialAccess不会加载整行,而是使 OleDbDataReader将数据作为流来加载。然后可以使用GetBytes或GetChars方法来指定开始读取操作的字节位置以及正在返回的数据的有限的缓冲区大小。尽管无需读取每个字段,但是需要按照字段的返回顺序读取它们。 一旦已经读过返回的数据流中某个位置的内容,就不能再从 OleDbDataReader中读取该位置或该位置之前的数据。

【例 19.13【项目:code19-013】读取数据表中的图片。

根据BMP文件的格式可知,BMP前两个字节是BMP文件头,为"BM",对应的十六进制值为 42 4D,由于北风数据库中的数据表使用的是OLE对象方式保存图片,所以它在BMP数据基础上增加了其它的数据。在获得图片字段数据后,只需要查找42 4D开始的位置,获得开始位置之后的数据就可以还原这个BMP图像了。

具体的代码如下:

    ……代码略

       private void Form1_Load(object sender, EventArgs e)

        {

            //建立OleDbConnection对象实例

            conn = new OleDbConnection();

            //设置OleDbConnection的连接字符串

            conn.ConnectionString = "Provider = Microsoft.Jet.OLEDB.4.0;data source=C:\\lessons\\Northwind.mdb;";

            //打开数据连接

            conn.Open();

 

            pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage;

 

            OleDbCommand command = new OleDbCommand();

            command.CommandText = "select 类别名称 from 类别";

            command.Connection = conn;

            //从类别表中获得类别名称并增加到ComboBox1中

            OleDbDataReader reader = command.ExecuteReader();

            if (reader.HasRows)

                while (reader.Read())

                    comboBox1.Items.Add(reader.GetString(0));

            reader.Close();

            comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;

        }

 

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)

        {

            OleDbCommand command = new OleDbCommand();

            command.CommandText = "select 图片 from 类别 where 类别名称='" + comboBox1.Text + "'";

            command.Connection = conn;

            //使用OleDbDataReader读取图片,使用SequentialAccess模式

            OleDbDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess & CommandBehavior.SingleResult & CommandBehavior.SingleRow);

            try

            {

                //存放从字段获得的数据

                byte[] fieldsData = new byte[] { };

                //每次从字段读取的字节数组

                byte[] buffer;

                //每次从字段读取的字节数组的长度

                int bufferLength = 1024;

                buffer = new byte[bufferLength];

                //每次使用OleDbDataReader的GetBytes方法时返回实际读取字节数的长度

                long readLength;

                int pos = 0;

                //开始读取

                reader.Read();

                //读取数据,数据较小时可以使用

                fieldsData =(byte[]) reader[0];

 

                或者将上一句代码替换为

                循环读取数据,数据较大的时候使用

                //while (true)

                //{

                //    //使用GetBytes方法读取数据

                //    readLength = reader.GetBytes(0, pos * bufferLength, buffer, 0, bufferLength);

                //    int imgDataLength;

                //    imgDataLength = fieldsData.Length;

                //    //保留fieldsData原来的数据基础上扩大fieldsData的大小

                //    Array.Resize(ref fieldsData,imgDataLength + (int)readLength);

                //    //将新读取的数据拷贝到fieldsData

                //    Array.Copy(buffer, 0, fieldsData, imgDataLength, readLength);

                //    //如果实际读取数据的长度小于设定的长度,那么表示已经读取完毕,退出循环

                //    if (readLength < bufferLength)

                //        break;

                //    pos += 1;

                //}

 

                //判断是否包含Bmp的标志 BM,即对应的十六进制值为 42 4D

                int bmpSign = -1;

                for(int i = 0; i< fieldsData.Length - 1;i++)

                {

                    if( fieldsData[i] == 0x42 & fieldsData[i + 1] == 0x4D)

                    {

                        bmpSign = i;

                        break;

                    }

                }

               

                if(bmpSign == -1)

                {

                    MessageBox.Show("不是有效的图片文件");

                    return;

                }

 

                //从fieldsData中提取出图像的数据保存到imgData

                byte[] imgData = new byte[fieldsData.Length - bmpSign];

                Array.Copy(fieldsData, bmpSign, imgData, 0, imgData.Length);

                //使用字节数组初始化一个MemoryStream对象

                System.IO.MemoryStream ms = new System.IO.MemoryStream(imgData);

                //从流获得一个image对象

                Image img = Image.FromStream(ms);

                pictureBox1.Image = img;

                //关闭流

                ms.Close();

            }

            catch( Exception ex)

            {

                MessageBox.Show(ex.Message);

            }

            finally

            {

                //关闭OleDbDataReader

                reader.Close();

            }

        }

运行结果如下图所示:

图19-33 显示类别图片

注意:以上操作是比较常见读取二进制数据值的一种操作,还可以使用以下代码:

fieldsData =(byte[]) reader[0];

替换while { }部分的代码。系统将获得指定字段里面的数据并自动转换为相应的数据类型的值。以上代码更简洁,可以在知道字段对应数据较少的情况下使用以上代码。

【例 19.14【项目:code19-014】向数据表中写入图片。

        private void btnChooseImage_Click(object sender, EventArgs e)

        {

            OpenFileDialog ofd = new OpenFileDialog();

            ofd.Filter = "所有图片|*.png;*.jpg;*.gif";

            if (ofd.ShowDialog() != DialogResult.OK)

                return;

            picType.Image = Image.FromFile(ofd.FileName);

        }

 

        private void btnAdd_Click(object sender, EventArgs e)

        {

            //检查数据是否符合要求

            if (txtType.Text.Trim() == "")

                return;

            if (txtTypeInfo.Text.Trim() == "")

                return;

            if (picType.Image == null)

                return;

 

            OleDbCommand odcommand = new OleDbCommand();

            //更新数据表的SQL语句

            odcommand.CommandText = "insert into 类别(类别名称,说明,图片) values(@typename,@typeinfo,@imgType)";

            odcommand.Connection = conn;

            //添加相应的数据参数

            odcommand.Parameters.Add("@typename", OleDbType.VarChar);

            odcommand.Parameters["@typename"].Value = txtType.Text;

            odcommand.Parameters.Add("@typeinfo", OleDbType.VarChar);

            odcommand.Parameters["@typeinfo"].Value = txtTypeInfo.Text;

 

            //按照数据表中类别的图片大小172*120建立图片

            Bitmap bmp = new Bitmap(172, 120);

            Graphics g = Graphics.FromImage(bmp);

            g.DrawImage(picType.Image, new Rectangle(0, 0, 172, 120), new Rectangle(0, 0, picType.Image.Width, picType.Image.Height), GraphicsUnit.Pixel);

            g.Dispose();

            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            //将图片以bmp格式保存到内存流中

            bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);

            //从内存流将数据保存到字节数组

            byte[] imgBuff = new byte[ms.Length];

            ms.Position = 0;

            imgBuff = ms.ToArray();

            ms.Close();

            //添加数据参数,这里使用LongVarBinary类型

            odcommand.Parameters.Add("@imgType", OleDbType.LongVarBinary);

            //对应的数据为字节数组

            odcommand.Parameters["@imgType"].Value = imgBuff;

            //执行ExecuteNonQuery

            odcommand.ExecuteNonQuery();

    }

运行结果如下图所示:

图19-34 向类别表中新增数据

由于这里只是保存的图片本身数据,而不是像类别表中图片字段是一个OLE对象,还添加有附加数据,所以,新增的图片数据不能像原有数据一样可以被画图程序打开。但是,使用【例 19.13】中的代码是可以正确显示图片的。

学习更多vb.net知识,请参看vb.net 教程 目录

学习更多C#知识,请参看C#教程 目录

 

相关文章:

19.4.6 读写数据库中的二进制数据

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 需要北风数据库的请留言自己的信箱。 北风数据库中&#xff0c;类别表的图片字段在【数据表视图】中显示为Bitmap Image&#xff1…...

如何在 Elasticsearch 中设置向量搜索 - 第二部分

作者&#xff1a;来自 Elastic Valentin Crettaz 了解如何在 Elasticsearch 中设置向量搜索并执行 k-NN 搜索。 本文是三篇系列文章中的第二篇&#xff0c;深入探讨了向量搜索&#xff08;也称为语义搜索&#xff09;的复杂性以及它在 Elasticsearch 中的实现方式。 第一部分重…...

【CXX-Qt】0 Rust与Qt集成实践指南(CXX-Qt)

CXX-Qt 是一个用于在 Rust 和 Qt 之间实现安全互操作的库。与通常的 Rust Qt 绑定不同&#xff0c;它提供了一种不同的方式来桥接 Qt 代码和 Rust 代码。CXX-Qt 认识到 Qt 和 Rust 代码具有不同的习惯&#xff0c;因此不能直接从一个语言包装到另一个语言。相反&#xff0c;它使…...

C++ 设计模式-适配器模式

适配器模式示例,包括多电压支持、类适配器实现、安全校验等功能: #include <iostream> #include <memory> #include <stdexcept>// 抽象目标接口:通用电源接口 class PowerOutlet {public:virtual ~PowerOutlet() = default;virtual int outputPower() c…...

【Elasticsearch】文本分析Text analysis概述

文本分析概述 文本分析使 Elasticsearch 能够执行全文搜索&#xff0c;搜索结果会返回所有相关的结果&#xff0c;而不仅仅是完全匹配的结果。 如果你搜索“Quick fox jumps”&#xff0c;你可能希望找到包含“A quick brown fox jumps over the lazy dog”的文档&#xff0c…...

【IDEA】2017版本的使用

目录 一、常识 二、安装 1. 下载IDEA2017.exe 2. 安装教程 三、基本配置 1. 自动更新关掉 2. 整合JDK环境 3. 隐藏.idea文件夹和.iml等文件 四、创建Java工程 1. 新建项目 2. 创建包结构&#xff0c;创建类&#xff0c;编写main主函数&#xff0c;在控制台输出内容。…...

ES6 Proxy 用法总结以及 Object.defineProperty用法区别

Proxy 是 ES6 引入的一种强大的拦截机制&#xff0c;用于定义对象的基本操作&#xff08;如读取、赋值、删除等&#xff09;的自定义行为。相较于 Object.defineProperty&#xff0c;Proxy 提供了更灵活、全面的拦截能力。 1. Proxy 语法 const proxy new Proxy(target, hand…...

数据结构——【二叉树模版】

#思路 1、二叉树不同于数的构建&#xff0c;在树节点类中&#xff0c;有数据&#xff0c;左子结点&#xff0c;右子节点三个属性&#xff0c;在树类的构造函数中&#xff0c;添加了变量maxNodes&#xff0c;用于后续列表索引的判断 2.GetTreeNode()函数是常用方法&#xff0c;…...

关闭浏览器安全dns解决访问速度慢的问题

谷歌浏览器加载速度突然变慢了&#xff1f;检查安全DNS功能(DoH)是否被默认开启。 谷歌浏览器在去年已经推出安全DNS功能(即DoH) , 启用此功能后可以通过加密的DNS增强网络连接安全性。例如查询请求被加密后网络运营商将无法嗅探用户访问的地址&#xff0c;因此对于增强用户的…...

【AIGC】语言模型的发展历程:从统计方法到大规模预训练模型的演化

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: AIGC | ChatGPT 文章目录 &#x1f4af;前言&#x1f4af;语言模型的发展历程&#xff1a;从统计方法到大规模预训练模型的演化1 统计语言模型&#xff08;Statistical Language Model, SLM&#xff09;&#xff1a;统…...

Spring Boot 中的事务管理:默认配置、失效场景及集中配置

Spring Boot 提供了强大的事务管理功能&#xff0c;基于 Spring 的 Transactional 注解。本文将详细介绍事务的默认配置、事务失效的常见场景、以及事务的几种集中配置方式&#xff0c;并给出相应的代码片段。 一、事务的默认配置 在 Spring Boot 中&#xff0c;默认情况下&am…...

DeepSeek 助力 Vue 开发:打造丝滑的进度条

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

deepseek的CoT优势、两阶段训练的有效性学习笔记

文章目录 1 DeepSeek的CoT思维链的优势1.2 open-r1的CoT训练数据1.3 ReAct任务与CoT任务适用场景 2 AI推理方向&#xff1a;deepseek与deepmind的两条路线的差异2.1 PRM与ORM的两大学派分支的差异2.2 DeepSeek-R1的两阶段训练概述 1 DeepSeek的CoT思维链的优势 DeepSeek跟之前…...

分享在职同时准备系统分析师和教资考试的时间安排

&#xff08;在职、时间有限、同时备考系统分析师考试和小学信息技术教资面试&#xff09;&#xff0c;以下是详细的备考计划&#xff0c;确保计划的可行性和通过性。 一、总体安排 时间分配&#xff1a; 每周周末&#xff08;2天&#xff09;用于系统分析师考试备考。工作日晚…...

浅谈Java Spring Boot 框架分析和理解

Spring Boot是一个简化Spring开发的框架&#xff0c;它遵循“约定优于配置”的原则&#xff0c;通过内嵌的Tomcat、Jetty或Undertow等容器&#xff0c;使得开发者能够快速构建独立运行的、生产级别的基于Spring框架的应用程序。Spring Boot包含了大量的自动配置功能&#xff0c…...

【开发心得】CentOS7编译Redis7.4.2打包RPM完整方案

概述 由于最近客户需要解决redis版本升级问题&#xff0c;故而全网寻找安全版本&#xff0c;redis7.4.x版本求而为果&#xff0c;只能自己编译了。 截止发文时间2025-02-12 最新稳定版的redis版本号为7.4.2 Security fixes (CVE-2024-46981) Lua script commands may lead t…...

【网络安全】常见网络协议

1. 网络协议概述 网络协议是网络上两个或多个设备使用的一组规则&#xff0c;用于描述传输顺序和数据结构。网络协议充当数据包中信息附带的指令。这些指令告诉接收设备如何处理数据。协议就像一种通用语言&#xff0c;让世界各地的设备能够相互通信和理解。 尽管网络协议在网…...

电路笔记(元器件):AD 5263数字电位计(暂记)

AD5263 是四通道、15 V、256位数字电位计&#xff0c;可通过SPI/I2C配置具体电平值。 配置模式&#xff1a; W引脚作为电位器的抽头&#xff0c;可在A-B之间调整任意位置的电阻值。也可将W与A(或B)引脚短接&#xff0c;A-W间的电阻总是0欧姆&#xff0c;通过数字接口调整电位器…...

MongoDB 的使用场景

一、内容管理系统 1. 博客平台 文章内容、作者信息、标签、评论等数据结构多样&#xff0c;MongoDB 的无模式特性可轻松应对。比如 WordPress 等博客系统&#xff0c;使用 MongoDB 能灵活存储不同格式和长度的文章内容&#xff0c;以及与文章相关的各种元数据。 2. 新闻网站…...

MongoDB 是什么

MongoDB 是一款文档型数据库&#xff0c;属于 NoSQL 数据库范畴。 一、基本概念 MongoDB 以文档的形式存储数据&#xff0c;文档类似于 JSON 对象&#xff0c;由键值对组成&#xff0c;它以 BSON&#xff08;Binary JSON&#xff09;格式存储在磁盘上&#xff0c;这种格式支持…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

C++.OpenGL (10/64)基础光照(Basic Lighting)

基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...