用VC怎样将一个二进制数据存到和SQL SERVER中呀???请帮帮忙!!!!!!急!!!

bigmm 2004-09-30 09:55:38
用VC怎样将一个二进制数据(一个buffer)存到和SQL SERVER中呀???请帮帮忙!!!!!!急!!!
...全文
464 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
fupinger 2004-09-30
  • 打赏
  • 举报
回复
Table have two fields:RY_ID(int),DATA(BLOB)

_RecordsetPtr pRecordset;
CString sql;
sql.Format("SELECT * FROM RYZP where RY_BH=%d", lRybh);//Open table
try
{
pRecordset.CreateInstance("ADODB.Recordset");
HRESULT hr = pRecordset->Open((_bstr_t)sql,_variant_t((IDispatch *)m_pConnection,true),adOpenDynamic,adLockPessimistic,adCmdText);
if(pRecordset->BOF || pRecordset->adoEOF)
{
pRecordset->AddNew();;//add a new record
pRecordset->Fields->GetItem(_variant_t("RY_BH"))->Value = lRybh
pRecordset->Update();
}
}
catch (_com_error e)
{
// CString str=(char*)e.Description();
// ::MessageBox(NULL,str+"\n又出毛病了。","提示",MB_OK | MB_ICONWARNING);
return FALSE;
}
VARIANT varChunk;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];

//VT_ARRAY | VT_UI1
const UINT ChunkSize = 4000;// maybe the file is very big,so we read it's data 4000 bytes every time.

CFile file;
//open a file and will save it's data to the BLOB field
if( !file.Open(strZpPathName, CFile::modeRead|CFile::shareDenyNone) )
{
return FALSE;
}
BYTE bVal[ChunkSize+1];
ULONG uIsRead=0;
//Create a safe array to store the array of BYTES
BOOL bSaveData = FALSE;
while(1)
{
try
{
uIsRead=file.Read(bVal,ChunkSize);
if(uIsRead==0)break;
rgsabound[0].cElements =uIsRead;
rgsabound[0].lLbound = 0;
psa = SafeArrayCreate(VT_UI1,1,rgsabound);

BYTE *buf;
::SafeArrayAccessData(psa, (void **)&buf);
for(long index=0;index<(long)uIsRead;index++)
{
buf[index]=bVal[index];
}
::SafeArrayUnaccessData(psa);

varChunk.vt = VT_ARRAY|VT_UI1;
varChunk.parray = psa;

pRecordset->Fields->GetItem(_variant_t("DATA"))->AppendChunk(varChunk);
}
catch (_com_error e)
{
CString str=(char*)e.Description();
::MessageBox(NULL,str,"提示",MB_OK | MB_ICONWARNING);
return FALSE;
}
::VariantClear(&varChunk);
::SafeArrayDestroyData( psa);
//save to BLOB
if(uIsRead<ChunkSize)
{
int nPos = strZpPathName.ReverseFind('\\');
CString str = strZpPathName.Right(strZpPathName.GetLength() - nPos - 1);
pRecordset->Fields->GetItem(_variant_t("WJM"))->Value = (_bstr_t)str;
pRecordset->Update();
break;
}
}//while(1)
file.Close();

m_bChangedRyzp = FALSE;
pRecordset->Close();
}


//these codes is used for save file to BLOB in DB.the file maybe *.txt,*.jpeg,*.wav,*.ocx,and so on.......it can be all format of you can think.
liuxianzhi 2004-09-30
  • 打赏
  • 举报
回复
应该是用BLOB类型,然后用ADO或者SQLSERVER的接口把他写入。
Soundboy 2004-09-30
  • 打赏
  • 举报
回复
开辟一块内存,把数据copy过去就可以操作了。
liuxianzhi 2004-09-30
  • 打赏
  • 举报
回复
我觉得你需要定义一个LOB类型的字段,然后把这些数据存储到这种字段中。
DentistryDoctor 2004-09-30
  • 打赏
  • 举报
回复
使blob字段。
54783szg 2004-09-30
  • 打赏
  • 举报
回复
下面是存储位图的二进制数据例子,你要存储二进制信息其基本原理一样

CFile imagefile;
if(0 == imagefile.Open("d:\\user\\bmp.bmp",CFile::modeRead))
return;
_RecordsetPtr pRs = NULL;
_ConnectionPtr pConnection = NULL;
_variant_t varChunk;
HRESULT hr;
BYTE* pbuf;
long nLength = imagefile.GetLength();
pbuf = new BYTE[nLength+2];
if(pbuf == NULL)
return; //allocate memory error;
imagefile.Read(pbuf,nLength); //read the file into memory

BYTE *pBufEx;
pBufEx = pbuf;
//build a SAFFERRAY
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;

_bstr_t strCnn("Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=CUSTOM;Data Source=SERVER");
try
{
//Open a connection
pConnection.CreateInstance(__uuidof(Connection));
hr = pConnection->Open(strCnn,"","",NULL); //Connect a DataBase
pRs.CreateInstance(__uuidof(Recordset));
pRs->Open("CustomInfo",_variant_t((IDispatch *) pConnection,true),adOpenKeyset,adLockOptimistic,adCmdTable); //Open a Table

// pRs->AddNew();
pRs->Fields->GetItem("Image")->AppendChunk(varBLOB);
pRs->Update();
pRs->Close();
pConnection->Close();
}
catch(_com_error &e)
{
// Notify the user of errors if any.
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
CString sError;
sError.Format("Source : %s \n Description : %s\n",(LPCSTR)bstrSource,(LPCSTR)bstrDescription);
AfxMessageBox(sError);
}
kugou123 2004-09-30
  • 打赏
  • 举报
回复
你可以把数据库的字段定义成字符型,
然后把二进制数以字符串形式存入,
以后需要的话,取出来转换一次即可。
snaill 2004-09-30
  • 打赏
  • 举报
回复
MSPY 2004-09-30
  • 打赏
  • 举报
回复
up
memory_xj 2004-09-30
  • 打赏
  • 举报
回复
上面的long lNum = 0;有误。其实是得到图像文件的大小,当然不能为0,知道意思就行了。
memory_xj 2004-09-30
  • 打赏
  • 举报
回复
可以用SQL server2000的image字段存储你的二进制数。流行的方法laiyiling(【陌生人 V2.0】) 也介绍了,其实对SAFEARRAY数组还真是不容易搞懂,呵呵~~懒哪。其实可以直接用将这个二进制数组复制进一个CByteArray数组,然后将这个CByteArray转化为COleVariant变量,将这个变量put_Value进数据库就可了。下面是我工程中的一个例子。
long lNum = 0;
LPBYTE filebuf = new BYTE[FILEBUFSIZE]; //在堆上建立一个BYTE数组
memset(filebuf, '\0', FILEBUFSIZE); //将内存清空
if (file.ReadHuge(filebuf, lNum) != lNum) //用一个图像文件内容填充数组
{
delete filebuf;
return FALSE;
}
CByteArray m_BitmapBuf; //创建一个ByteArray类转存filebuf内的二进制数据
m_BitmapBuf.SetSize(lNum); //初始空间大小
for (long int i = 0; i < lNum; i++) //将二进制数据复制进CByteArray中。
m_BitmapBuf.SetAt(i, filebuf[i]);
COleVariant varBitmap(m_BitmapBuf); //关键!将CByteArray类转换为COleVariant变量
//以下就是用ADO向image字段中保存该二进制数据,当然也可以用其它ADO的其它保存方法
ADODB::FieldsPtr ptrFields = NULL;
ADODB::FieldPtr ptrField = NULL;
ptrFields = m_ptrRS->Fields; //m_ptrRS是你用ADO打开的记录集
m_ptrRS->AddNew();
ptrFields->get_Item((_variant_t)i, &ptrField);
ptrField->put_Value(varBitmap); //保存二进制数据
zhaogaojian 2004-09-30
  • 打赏
  • 举报
回复
简易楼主直接用那个封装的Ado类,就省去这么多麻烦了
nwpulipeng 2004-09-30
  • 打赏
  • 举报
回复
帮顶混分
OriesMap 2004-09-30
  • 打赏
  • 举报
回复
参看网址,有代码的。
http://www.vckbase.com/code/viewcode.asp?id=2488
Kudeet 2004-09-30
  • 打赏
  • 举报
回复
_RecordsetPtr 是什么东东?
-----------------------
看来楼主还没有用过ADO啊!建议你先看看ADO操作数据库的基础文章,要不然上面的你也难看懂啊!

http://dev.csdn.net/develop/article/21/21087.shtm
Kudeet 2004-09-30
  • 打赏
  • 举报
回复
使用ADO实现BLOB数据的存取 -- ADO开发实践之二

一、前言
在上一篇文章《ADO第一次亲密接触》中我们详细介绍了ADO基本的操作方法,在实际的开发过程中我们常常需要存储较大的二进制数据对象,比如:图像、音频文件、或其它二进制数据,这些数据我们称之为二进制大对象BLOB(Binary Large Object),其存取的方式与普通数据有所区别。本文将介绍利用ADO在数据库中存取BLOB数据的具体实现过程,并给出实现图像存取显示的完整示例工程。


二、前期准备
首先我们建立一张名为userinfo的表,包含三个字段:id,username,old,photo,其中photo是一个可以存储二进制数据的字段。
2.1 在SQL SERVER中我们可以在Query Analyzer中直接输入如下语句创建:


CREATE TABLE [dbo].[userphoto] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[username] [varchar] (50) NULL ,
[old] [int] NULL ,
[photo] [image] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
其中photo我们定义为image类型的字段。


2.2 在ACCESS中创建的方法如下:
建立一张新表包括id,username,old,photo四个字段,然后打开表,选视图菜单中设计视图,将id设置为自动编号的递增长整型,username为文本,old为数字,photo为OLE对象。
在我们的示例工程中已经包含了一个建立好的ACCESS2000的库,你可以直接拿来使用。


三、具体步骤
3.1 BLOB数据的保存
BLOB类型的数据无法用普通的方式进行存储,我们需要使用AppendChunk函数,AppendChunk包含在Field对象中,原型如下:
HRESULT AppendChunk (const _variant_t & Data );
从函数原型中可以看到关键的问题是我们需把二进制数据赋值给VARIANT类型的变量,下面我们给出具体的代码并作简单的分析:




///假设m_pBMPBuffer指针指向一块长度为m_nFileLen的二进制数据,并且已经成功打开了记录集对象m_pRecordset///

char *pBuf = m_pBMPBuffer;
VARIANT varBLOB;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[1];

m_pRecordset->AddNew(); ///添加新记录
m_pRecordset->PutCollect("username",_variant_t("小李")); ///为新记录填充username字段
m_pRecordset->PutCollect("old",_variant_t((long)28); ///填充old字段
if(pBuf)
{
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = m_nFileLen;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound); ///创建SAFEARRAY对象
for (long i = 0; i < (long)m_nFileLen; i++)
SafeArrayPutElement (psa, &i, pBuf++); ///将pBuf指向的二进制数据保存到SAFEARRAY对象psa中
varBLOB.vt = VT_ARRAY | VT_UI1; ///将varBLOB的类型设置为BYTE类型的数组
varBLOB.parray = psa; ///为varBLOB变量赋值
m_pRecordset->GetFields()->GetItem("photo")->AppendChunk(varBLOB);///加入BLOB类型的数据
}
m_pRecordset->Update(); ///保存我们的数据到库中
至此我们的数据已经成功地保存到了数据库中,接下来我们所要做的工作便是将该数据提取出来,让我们继续吧!

3.2 BLOB数据的读取
对应于保存数据时我们所使用的AppendChunk函数,读取数据应该使用GetChunk函数,GetChunk的原型如下:
_variant_t GetChunk (long Length );
给出数据的长度后GetChunk将返回包含数据的VARIANT类型变量,然后我们可以利用SafeArrayAccessData函数得到VARIANT变量中指向数据的char *类型的指针,以方便我们的处理,具体代码如下:



long lDataSize = m_pRecordset->GetFields()->GetItem("photo")->ActualSize;///得到数据的长度
if(lDataSize > 0)
{
_variant_t varBLOB;
varBLOB = m_pRecordset->GetFields()->GetItem("photo")->GetChunk(lDataSize);
if(varBLOB.vt == (VT_ARRAY | VT_UI1)) ///判断数据类型是否正确
{
char *pBuf = NULL;
SafeArrayAccessData(varBLOB.parray,(void **)&pBuf); ///得到指向数据的指针
/*****在这里我们可以对pBuf中的数据进行处理*****/
SafeArrayUnaccessData (varBLOB.parray);
}
}
以上我们成功实现了BLOB数据在数据库中的存取,为了让大家有现成的例子可以参考,本文提供了示例工程,在示例工程中我们在数据库中保存图像数据,并可以对这些图像进行浏览、修改,该例子还涉及到如何用char *指向的BMP文件数据创建BITMAP对象然后显示出来。

bigmm 2004-09-30
  • 打赏
  • 举报
回复
_RecordsetPtr 是什么东东?

16,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧