在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。

作者:邵盛松 2009-09-05

前言

1关于的BLOB(Binary)数据的存储和读取功能主要参考了MSDN上的一篇《AppendChunk and GetChunk Methods Example (VC++)》,原文地址是http://msdn.microsoft.com/en-us/library/ms807920.aspx。还有www.vckbase.com上有一篇文章《使用ADO实现BLOB数据的存取 -- ADO开发实践之二》,原文地址是http://www.vckbase.com/document/viewdoc/?id=252

我在这篇博文当中增加了对BLOB(Binary)数据的存储,读取代码的分析。

2关于BLOB(Binary)数据的修改,我试验过多种方法,这个问题也花了比较长的时间才得到解决,原来的方法是从文件读取的数据,将更改的数据转化为CString类型,然后采用SQL的UPDATE语句进行数据的更新。后来在CSDN论坛上得到了vieri_ch的帮助,问题得到了比较好的一种解决方案。

实现方法:

1  BLOB(Binary)数据的存储,将一个文件存储到数据库。

存储部分代码分析写的比较详细,因为这里面得一些COM 结构和API需要说明一下

m_pRs为_RecordsetPtr类型

CFile   fileAdd;

if(fileAdd.Open(要存储文件的路径,CFile::modeRead)==0)    //打开文件

return;

_variant_t   varChunk;

long   nLength   =   fileAdd.GetLength();

BYTE*   pbuf;

pbuf   =   new   BYTE[nLength];

if(pbuf==NULL)

return;

fileAdd.Read(pbuf,nLength);

BYTE   *pBufEx;

pBufEx   =   pbuf;

SAFEARRAY*   psa;

SAFEARRAYBOUND   rgsabound[1];

rgsabound[0].lLbound   =   0;

rgsabound[0].cElements   =   nLength;

psa   =   SafeArrayCreate(VT_UI1, 1, rgsabound);

for   (long   i   =   0;   i   <   nLength;   i++)

SafeArrayPutElement(psa,&i, pBufEx++);

VARIANT   varBLOB;

varBLOB.vt   =   VT_ARRAY   |   VT_UI1;

varBLOB.parray   =   psa;

m_pRs->ADOFields->GetItem(_variant_t("BLOB类型字段的名称"))->AppendChunk(varBLOB);

m_pRs->Update();

m_pRs->Close();

在代码中有一个SAFEARRAY和SAFEARRAYBOUND类型,该类型在头文件OAIdl.h中定义

typedef struct tagSAFEARRAY

{

USHORT cDims;

USHORT fFeatures;

ULONG cbElements;

ULONG cLocks;

SAFEARRAYBOUND rgsabound[ 1 ];

}SAFEARRAY;

SAFEARRAY结构体中包含了SAFEARRAYBOUND类型。

先说SAFEARRAYBOUND结构

cElements表示数组中元素的个数。

lLbound表示数组的下界。

代码中SAFEARRAYBOUND元素个数为读取文件的大小,下界是0

操作SAFEARRAY类型是由COM提供了一套API来处理的。oleauto.h 头文件中可以看到很多关于操作SAFEARRAY数据类型的API.以下少列出几个

WINOLEAUTAPI SafeArrayAllocDescriptor(UINT cDims, SAFEARRAY ** ppsaOut);

WINOLEAUTAPI SafeArrayAllocDescriptorEx(VARTYPE vt, UINT cDims, SAFEARRAY ** ppsaOut);

WINOLEAUTAPI SafeArrayAllocData(SAFEARRAY * psa);

WINOLEAUTAPI_(SAFEARRAY *) SafeArrayCreate(VARTYPE vt, UINT cDims, SAFEARRAYBOUND * rgsabound);

SAFEARRAY为什么会称为安全数组?

从名字上看是安全数组的意思。比如我们第一个数组,数组的大小为10,数组的下界是从0开始,这时我们访问下界为10的元素,这时就发生了错误,以为数组的下界最大为9。SAFEARRAY这样定义结构的作用是实现COM API函数可以限制我们访问下界为10的元素和其他一些安全操作数组的行为等

SAFEARRAY结构说明

成员 描述

cDims 数组的维数

fFeatures 标志

cbElements 数组元素的大小

cLocks 一个计数器,用来跟踪该数组被锁定的次数

pvData  指向数据缓冲的指针

标志表示是在堆上创建还是在栈上创建等还包括其他一些标志

FADF_AUTO 0x0001

在栈上创建数组

FADF_STATIC 0x0002

在堆上创建数组

FADF_EMBEDDED 0x0004

在结构中创建

FADF_FIXEDSIZE 0x0010

不能改变数组大小

FADF_RECORD 0x0020

记录容器

FADF_HAVEIID 0x0040

有IID 身份标记 数组

FADF_HAVEVARTYPE 0x0080

VT 类型数组

FADF_BSTR 0x0100

BSTR数组

FADF_UNKNOWN 0x0200

IUnknown* 数组

FADF_DISPATCH 0x0400

IDispatch* 数组

FADF_VARIANT 0x0800

VARIANTs数组

FADF_RESERVED 0xF0E8

余留,将来使用

COM API函数说明SafeArrayCreate创建数组。参数VT_UI1是表示unsigned int 1字节整数(BYTE)数组

vt是数组类型、lLbound是数组下界值(最小下标)和数组长度

SafeArrayPutElement函数是向一个安全数组中添加一个值,代码中采用循环一个一个得添加

ADO方法

AppendChunk将数据追加到大型文本、二进制数据 Field 或 Parameter 对象。

语法

object.AppendChunk Data

参数

object   Field 或 Parameter 对象

Data  变体型,包含追加到对象中的数据。

2  BLOB(Binary)数据的读取

将数据库中的数据读出并写入文件。

long   lDataLength = m_pRs->GetADOFields()->GetItem(_variant_t("BLOB类型的字段"))->ActualSize;

if (lDataLength>0)

{

_variant_t   varBLOB;

varBLOB=m_pRs->GetADOFields()->GetItem(_variant_t("BLOB类型的字段"))->GetChunk(lDataLength);

if(varBLOB.vt== (VT_ARRAY|VT_UI1) && varBLOB.vt!=VT_EMPTY && varBLOB.vt!=VT_NULL )

{

BYTE   *pBuf   =   NULL;

pBuf   =   (BYTE*)GlobalAlloc(GMEM_FIXED,lDataLength);

SafeArrayAccessData(varBLOB.parray,(void   **)&pBuf);

strFileName表示生成包含文件名的路径

CFile   outFile(strFileName,CFile::modeCreate|CFile::modeWrite); //构造新文件,如果文件存在,则长度变为0

outFile.Write(pBuf,lDataLength);

outFile.Close();

SafeArrayUnaccessData (varBLOB.parray);

}

}

m_pRs->Close();

3  BLOB(Binary)数据的修改

CFileException eFile;

CFile   fileSave;

strPath表示需要修改文件的路径

fileSave.Open(strPath,CFile::modeReadWrite|CFile::shareDenyWrite|CFile::shareDenyRead|CFile::typeBinary,&eFile);

_variant_t   varChunk;

long   nLength   =    fileSave.GetLength();

BYTE*   pbuf;

pbuf   =   new   BYTE[nLength];

if(pbuf   == NULL) return;

fileSave.Read(pbuf,nLength);

fileSave.Close();

BYTE   *pBufEx;

pBufEx   =   pbuf;

SAFEARRAY*   psa;

SAFEARRAYBOUND   rgsabound[1];

rgsabound[0].lLbound   =   0;

rgsabound[0].cElements   =   nLength;

psa   =   SafeArrayCreate(VT_UI1, 1, rgsabound);

for   (long   i   =   0;   i   <   nLength;   i++)

SafeArrayPutElement(psa,&i, pBufEx++);

VARIANT   varBLOB;

varBLOB.vt   =   VT_ARRAY   |   VT_UI1;

varBLOB.parray   =   psa;

CString strSQL;

strSQL.Format(_T("UPDATE 表名 SET BLOB字段名=? WHERE ID='1'");

m_pCom.CreateInstance(__uuidof(Command));

m_pCom->ActiveConnection = m_pCon;

m_pCom->CommandText = _bstr_t(strSQL);

m_pCom->CommandType = adCmdText;

m_pCom->Parameters->Append(m_pCom->CreateParameter(_T("@参数名"),adVarBinary, adParamInput, -1, varBLOB));

m_pCom->Execute(NULL,NULL,adCmdText);

4 BLOB(Binary)数据的修改

 

删除比较简单一点,同时表定义该字段允许为空

执行一个SQL语句就可以了

UPDATE 表名 SET BLOB字段名 = NULL WHERE ID=1

以上程序已经在Visual C++2005 Unicode下调试通过

在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。的更多相关文章

  1. VC++下使用ADO操作数据库

    VC++下使用ADO操作数据库主要要用到 _ConnectionPtr,_CommandPtr,_RecordsetPtr三个ADO对象指针,我查找了相关资料,发现网上源码很多,但是都相对凌乱,于是自 ...

  2. VC++下封装ADO类以及使用方法

    操作系统:windows 7软件环境:visual studio 2008 .Microsoft SQL 2005本次目的:介绍一个已经封装的ADO类,简单说明怎么导入使用 首先声明一下,这个封装的A ...

  3. [转]VC++下使用ADO操作数据库

    (1).引入ADO类 1 2 3 #import "c:program filescommon filessystemadomsado15.dll" no_namespace re ...

  4. VC下Debug和Release区别

    整理日: 2015年3月23日 最近写代码过程中,发现 Debug 下运行正常,Release 下就会出现问题,百思不得其解,而Release 下又无法进行调试,于是只能采用printf方式逐步定位到 ...

  5. 在VC下显示JPEG、GIF格式图像的一种简便方法

    在VC下显示JPEG.GIF格式图像的一种简便方法 一. 引言  JPEG图像压缩标准随然是一种有损图像压缩标准,但由于人眼视觉的不敏感,经压缩后的画质基本没有发生变化,很快便以较高的压缩率得到了广泛 ...

  6. 使用ADO实现BLOB数据的存取 -- ADO开发实践之二

    使用ADO实现BLOB数据的存取 -- ADO开发实践之二 http://www.360doc.com/content/11/0113/16/4780948_86256633.shtml 一.前言 在 ...

  7. 在Ubuntu 12.04下采用apt-get的方法安装Qt4

    在Ubuntu 12.04下采用apt-get的方法安装Qt4 注:之前发表的一篇博客是采用编译源码的方式安装Qt4,这是很有用的方式,因为源码安装对于所有系统都是通用的,其次,在使用交叉编译器的时候 ...

  8. VC下加载JPG/GIF/PNG图片的两种方法

    转载自:http://blog.sina.com.cn/s/blog_6582aa410100huil.html 仅管VC有提供相应的API和类来操作bmp位图.图标和(增强)元文件,但却不支持jpg ...

  9. VS2005环境下采用makefile编译、使用libjpeg.lib函数库

    1.从www.ijg.org下载源码,解压后得到文件夹jpeg-8d 2.在文件夹里新建jconfig.h文件,将jconfig.vc里的内容拷到jconfig.h中 3.编译. Run->CM ...

随机推荐

  1. 大米网赚项目介绍,官方唯一客服QQ:712994168

    大米平台项目来源   QQ:712994168 大米软件本质上是一个高质量网赚项目收集和发布平台,该平台的所有项目都是经过专业的测试团队实测有效的项目和教程,只要去做绝对可以赚钱.平台里面的项目类型包 ...

  2. 推荐一个简单、轻量、功能非常强大的C#/ASP.NET定时任务执行管理器组件–FluentScheduler定时器

    在C#WINFORM或者是ASP.NET的WEB应用程序中,根据各种定时任务的需求,比如:每天的数据统计,每小时刷新系统缓存等等,这个时候我们得应用到定时器这个东东. .NET Framework有自 ...

  3. 【Linux】【通信】1.ping不通

    关于为什么ping不通有很多种原因,但直接的表象就网络之间没有成功进行通讯: 在构建虚拟机和win之间的交互时,主要使用了3种网络模式: 桥接bridge VMnet0 主机host     VMne ...

  4. 【 2013 Multi-University Training Contest 3 】

    HDU 4622 Reincarnation 枚举字符串的起点,构造后缀自动机,每次插入一个字符,就能统计得到当前不同字串的个数,预处理出所有的询问. #include<cstdio> # ...

  5. mongodb 备份 还原 导出 导入

    张映 发表于 2013-12-03 分类目录: nosql 标签:mongodb, 备份, 导入, 导出, 还原 mongodb数据备份和还原主要分为二种,一种是针对于库的mongodump和mong ...

  6. win环境 yii2 框架 overtrue/wechat 包 由 sys_get_temp_dir 引发的 the directory "c:\Windows" is not writable

    vendor\overtrue\wechat\src\Foundation\Application.php registerBase 方法 在初始化属性时 $this['cache'] = funct ...

  7. JAVA 如何把request请求的参数,快速放到model对象中

    因为项目需要,需要从request中读取大量的参数. 因为本人过懒,所以写了个方法把request参数,直接放到对应的类中. 参数 String str="aa,bb,cc"; P ...

  8. Text Justification

    在一段时间没刷题之后,我发现脑子严重地滞涩了.这题AC花了好大力气,出现了Memory Limit Exceed,Core Dump,以及各种普通的编译.运行错误.MLE 和 CD错误是比较难检查的, ...

  9. Asp.net MVC路由机制

    C:/Windows/Microsoft.NET/Framwork/v4.0.30319/config/web.config-> httpModules-> System.Web.Rout ...

  10. js报错:email() is not a function

    email() is not a function 明明是一个函数,但火狐控制台真J.. 由于JSP文件是别人写好直接使用的,所以,来回测试,折腾!最后,没办法,一段一段代码删除测试,才发现.有for ...