在VC下采用ADO实现BLOB(Binary)数据的存储,读取,修改,删除。
在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)数据的存储,读取,修改,删除。的更多相关文章
- VC++下使用ADO操作数据库
VC++下使用ADO操作数据库主要要用到 _ConnectionPtr,_CommandPtr,_RecordsetPtr三个ADO对象指针,我查找了相关资料,发现网上源码很多,但是都相对凌乱,于是自 ...
- VC++下封装ADO类以及使用方法
操作系统:windows 7软件环境:visual studio 2008 .Microsoft SQL 2005本次目的:介绍一个已经封装的ADO类,简单说明怎么导入使用 首先声明一下,这个封装的A ...
- [转]VC++下使用ADO操作数据库
(1).引入ADO类 1 2 3 #import "c:program filescommon filessystemadomsado15.dll" no_namespace re ...
- VC下Debug和Release区别
整理日: 2015年3月23日 最近写代码过程中,发现 Debug 下运行正常,Release 下就会出现问题,百思不得其解,而Release 下又无法进行调试,于是只能采用printf方式逐步定位到 ...
- 在VC下显示JPEG、GIF格式图像的一种简便方法
在VC下显示JPEG.GIF格式图像的一种简便方法 一. 引言 JPEG图像压缩标准随然是一种有损图像压缩标准,但由于人眼视觉的不敏感,经压缩后的画质基本没有发生变化,很快便以较高的压缩率得到了广泛 ...
- 使用ADO实现BLOB数据的存取 -- ADO开发实践之二
使用ADO实现BLOB数据的存取 -- ADO开发实践之二 http://www.360doc.com/content/11/0113/16/4780948_86256633.shtml 一.前言 在 ...
- 在Ubuntu 12.04下采用apt-get的方法安装Qt4
在Ubuntu 12.04下采用apt-get的方法安装Qt4 注:之前发表的一篇博客是采用编译源码的方式安装Qt4,这是很有用的方式,因为源码安装对于所有系统都是通用的,其次,在使用交叉编译器的时候 ...
- VC下加载JPG/GIF/PNG图片的两种方法
转载自:http://blog.sina.com.cn/s/blog_6582aa410100huil.html 仅管VC有提供相应的API和类来操作bmp位图.图标和(增强)元文件,但却不支持jpg ...
- VS2005环境下采用makefile编译、使用libjpeg.lib函数库
1.从www.ijg.org下载源码,解压后得到文件夹jpeg-8d 2.在文件夹里新建jconfig.h文件,将jconfig.vc里的内容拷到jconfig.h中 3.编译. Run->CM ...
随机推荐
- Adb refused a command 解决方法
原文:How To Fix Android Error Adb Refused A Command 地址:http://downloadfixit.com/android-error-adb-refu ...
- Linux 下使用Visual Studio Code
1.下载:https://az764295.vo.msecnd.net/stable/db71ac615ddf9f33b133ff2536f5d33a77d4774e/VSCode-linux-x64 ...
- Provisioning Services 7.6 入门到精通系列之二:基础架构环境
在阅读本博文之前强烈建议同学们提前了解Citrix XenDesktop和XenApp等产品,并对PVS相关产品概念架构有深入的理解. 1.1 以下是在上一章节中规划的本次测试环境的配置清单(后续 ...
- placeholder 颜色更改
::-webkit-input-placeholder { /* WebKit browsers */ color: #999; } :-moz-placeholder { /* Mozilla Fi ...
- 判断IE版本的HTML语句详解,如:[if lte IE 9]……[endif]
我们常常会在网页的HTML里面看到形如[if lte IE 9]……[endif]的代码,表示的是限定某些浏览器版本才能执行的语句,那么这些判断语句的规则是什么呢?请看下文: <!--[if ! ...
- 使用VMware Workstation 12.5.2新建虚拟机
关于VMware版本:VMware10可以支持32位和64位操作系统,VMware11及以上版本只能支持64位Win7及以上版本的操作系统!同时,VMware Workstation 10.0正式版发 ...
- NodeJs使用asyncAwait两法
async/await使用同步的方式来书写异步代码,将异步调用的难度降低到接近于0,未来必将大放异彩.然而在当下,由于标准化的缓存步伐,async/await尚在ES7的草案中.为了尝先,特试用了下面 ...
- php截取utf-8中文字符串乱码的解决方法
/** * PHP截取UTF-8字符串,解决半字符问题. * 英文.数字(半角)为1字节(8位),中文(全角)为2字节 * @return 取出的字符串, 当$len小于等于0时, 会返回整个字符串 ...
- PHP初步(上)
一.php语法 PHP是一种嵌入式脚本语言,所以,我们需要标记出哪些是PHP代码,哪些是html代码.当html和php代码进行混编的时候,文件必须要以php结尾(否则Apache不会将这个文件交给p ...
- c语言计算矩阵特征值和特征向量-1(幂法)
#include <stdio.h> #include <math.h> #include <stdlib.h> #define M 3 //方阵的行数 列数 #d ...