sql sever 2000 存储文件 vc 各位大虾: 请问如何将一个文件(任意一个文件)存储到sql server 2000数据库中(是否可以存在一个字段当中),使用vc. 应该用什么方法,字段应该设置成什么格式?希望能提供代码! 谢谢! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 使用blob字段保存任意大小的二进制数据,不过代码访问这种字段稍微复杂一些。 4f正解,设定数据库时用IAMGE类型 ADO 方式try{ //先用 CFileDialog 得到文件 FileName CFile myfile; CFileException e;//打开文件 if( !myfile.Open(FileName, CFile::modeRead, &e ) ) { return; } BYTE* pbuf; long len = myfile.GetLength(); pbuf = new BYTE[len]; if(pbuf == NULL) return; //allocate memory error; myfile.ReadHuge(pbuf,len); //read the file into memory BYTE *pBufEx; pBufEx = pbuf;// 构造安全数组并放到一个varint变量中 SAFEARRAY* psa; SAFEARRAYBOUND rgsabound[1]; rgsabound[0].lLbound = 0; rgsabound[0].cElements = len; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); for (long i = 0; i < len; i++) SafeArrayPutElement (psa, &i, pBufEx++); _variant_t varBLOB; varBLOB.vt = VT_ARRAY | VT_UI1; varBLOB.parray = psa; delete []pbuf; myfile.Close(); if(len>0) rs->Fields->GetItem(/*IMAGE字段*/)->AppendChunk(varBLOB); }catch (...) { return; } 楼上的代码还是有些不明白的地方我是用sql语句,应该如何写呢?TO jameshooo :请说的详细一些,是否有具体的代码? 7楼给的就是代码。纯粹的SQL语句不能访问blob数据。 那应该怎么写进去啊?怎么读出来啊?SAFEARRAY* psa; SAFEARRAYBOUND rgsabound[1]; rgsabound[0].lLbound = 0; rgsabound[0].cElements = len; psa = SafeArrayCreate(VT_UI1, 1, rgsabound); for (long i = 0; i < len; i++) SafeArrayPutElement (psa, &i, pBufEx++); _variant_t varBLOB; varBLOB.vt = VT_ARRAY ¦ VT_UI1; varBLOB.parray = psa; delete []pbuf; myfile.Close(); if(len>0) rs->Fields->GetItem(/*IMAGE字段*/)->AppendChunk(varBLOB); 这一段能不能给点注释啊?如何读出来呢? AppendChunk是写数据,GetChunk是读数据。二进制数据读写必须使用SAFEARRAY,所以看起来代码有点复杂。 不是可不可以的问题,估计当作一个BLOB插入肯定没问题,但是这是数据库设计的大忌吧,好多数据库设计的建议都是不要这么做。这样做至少从我看来没有任何好处,坚持一个没有好处的算法不知道在干吗 按照自己的需要去选择技术去做。但是可以考虑1:存储文件路径到数据库中。2:可以把文件内容存储到数据库中。其中2,可以用image类型去存二进制流,方便你序列化和反序列化。或者直接存文件字符串进去。 在实现7楼的代码时,还有两个问题,希望能得到大家帮忙:1、在sql sever中建表时,数据类型选择 image 数据类型时,长度不能改变,只能为16,这是不是太小了啊?如果存储文件较大怎么办啊?2、rs->Fields->GetItem(/*IMAGE字段*/)->AppendChunk(varBLOB);这段话中,rs是这样 _RecordsetPtr rs 定义的吗?再就是怎么确定是哪个表呢?连接数据库只能是连接数据库,不能确定是哪个表啊。假如我的表的名称是record,字段名称是filecontent,调用时写成record.filecontent可以吗? BLOB 数据在 SQL Server 数据库中主要由 IMAGE 类型体现,最大容量为 2GB 。其存储方式不同于普通的数据类型,对于普通类型的数据系统直接在用户定义的字段上存储数据值,而对于 IMAGE 类型数据,系统开辟新的存储页面来存放这些数据,表中 IMAGE 类型数据字段存放的仅是一个 16 字节的指针,该指针指向存放该条记录的 IMAGE 数据的页面。rs是这样 _RecordsetPtr rs 定义的吗是再就是怎么确定是哪个表呢?void OnRecordsetAddnew(){ _RecordsetPtr pRS; HREFTYPE hr = NOERROR; _bstr_t bstrQuery("SELECT * FROM [record] WHERE myID IS NULL"); //假设myID是主键 ,这里打开一个不包含记录的记录集 _variant_t vtNULL; vtNULL.vt = VT_ERROR; vtNULL.scode = DISP_E_PARAMNOTFOUND; try { hr = pRS.CreateInstance(__uuidof(Recordset)); if(SUCCEEDED(hr)) { pRS->PutRefActiveConnection(m_pConnection); //m_pConnection 是以打开的 _ConnectionPtr 变量 hr = pRS->Open(_variant_t(bstrQuery), vtNULL, adOpenForwardOnly, adLockOptimistic, adCmdText); if (SUCCEEDED(hr)) { //方案1 //字段名list COleSafeArray vaFieldList; vaFieldList.CreateOneDim(VT_VARIANT,2); //假设有2个字段 LONG larrayIndex[1]; //ID字段名 larrayIndex[0] = 0; vaFieldList.PutElement(larrayIndex,&(_variant_t("myID"))); //filecontent字段名 larrayIndex[0] = 1; vaFieldList.PutElement(larrayIndex,&(_variant_t("filecontent"))); //字段的值list COleSafeArray vaValueList; vaValueList.CreateOneDim(VT_VARIANT,2); //ID值 larrayIndex[0] = 0; vaValueList.PutElement(larrayIndex,&(_variant_t("001")); //filecontent字段值 larrayIndex[0] = 1; vaValueList.PutElement(larrayIndex,&varBLOB)); //varBLOB 是 7楼 代码的 _variant_t varBLOB; pRS->AddNew(vaFieldList,vaValueList); pRS->Close(); //方案2 // pRS->AddNew(); // pRS->PutCollect("myID",_variant_t("001")); // pRS->Fields->GetItem("filecontent")->AppendChunk(varBLOB);//varBLOB 是 7楼 代码的 _variant_t varBLOB; // pRS->Update(); // pRS->Close(); } } } catch(_com_error & e) { TRACE("Error : %081x. \n",e.Error()); TRACE("ErrorMessage : %s. \n",e.ErrorMessage()); TRACE("Source : %s. \n",(LPCTSTR)_bstr_t(e.Source())); TRACE("Description : %s. \n",(LPCTSTR)_bstr_t(e.Description())); } catch(...) { TRACE("\n *** Unhandled Exception *** \n"); }} 如果楼主要求性能好的可以考虑使用OLEDB API 我还没有实验17楼大哥的代码是否可以,请问 tvman 大哥: 你的方案二可以用吗?再就是如何从数据库里读出来文件呢?但是在运行7楼大哥的代码时报错了,是Runtime Error. 请问是怎么回事 //pRS->Fields->GetItem("filecontent")->AppendChunk(varBLOB); 也可以改成 pRS->PutCollect("filecontent",varBLOB); // pRS->Update() 后释放空间 SAFEARRAY ::SafeArrayDestroyData(psa);//从数据库获取数据_variant_t data = pRS->GetCollect("filecontent"); if(::GetFileAttributes(name)!=-1) //name 是你的文件名 ::SetFileAttributes(name,FILE_ATTRIBUTE_NORMAL);//保存到文件CFile file;if(file.Open(name,CFile::modeCreate|CFile::modeWrite)){ file.WriteHuge(data.parray->pvData,data.parray->rgsabound[0].cElements); file.Close();} mfc创建控件!!菜鸟求救!! 菜鸟问:如何在多文档模式中的Doc类中获取某个活动子窗口的大小? 求助高手,WM_SysCommand 怎么添加? OpenGL在特定条件下的崩溃--浮点协处理器异常 如何把信息写入文本文件,有简单的示例么? 怎么样改变我自己控件的大小??? 请问在一个属性页里面,可不可以把命令都写在PAGE里面而不传到SHEET? 关于CMSFlexGrid,CEdit显示问题 请问哪里能找到CCD,CMOS图象传感器原理的文章? 为什么电脑放VCD时用常规方法无法截屏? 如何更改alt+tab的图标 关于逻辑磁盘粉碎的问题 急!在线等
try{
//先用 CFileDialog 得到文件 FileName
CFile myfile;
CFileException e;
//打开文件
if( !myfile.Open(FileName, CFile::modeRead, &e ) )
{
return;
}
BYTE* pbuf;
long len = myfile.GetLength();
pbuf = new BYTE[len];
if(pbuf == NULL)
return; //allocate memory error;
myfile.ReadHuge(pbuf,len); //read the file into memory
BYTE *pBufEx;
pBufEx = pbuf;
// 构造安全数组并放到一个varint变量中 SAFEARRAY* psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = len;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
for (long i = 0; i < len; i++)
SafeArrayPutElement (psa, &i, pBufEx++);
_variant_t varBLOB;
varBLOB.vt = VT_ARRAY | VT_UI1;
varBLOB.parray = psa;
delete []pbuf;
myfile.Close();
if(len>0)
rs->Fields->GetItem(/*IMAGE字段*/)->AppendChunk(varBLOB);
}catch (...) {
return;
}
我是用sql语句,应该如何写呢?
TO jameshooo :
请说的详细一些,是否有具体的代码?
怎么读出来啊?SAFEARRAY* psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = len;
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
for (long i = 0; i < len; i++)
SafeArrayPutElement (psa, &i, pBufEx++);
_variant_t varBLOB;
varBLOB.vt = VT_ARRAY ¦ VT_UI1;
varBLOB.parray = psa;
delete []pbuf;
myfile.Close();
if(len>0)
rs->Fields->GetItem(/*IMAGE字段*/)->AppendChunk(varBLOB);
这一段能不能给点注释啊?如何读出来呢?
二进制数据读写必须使用SAFEARRAY,所以看起来代码有点复杂。
其中2,可以用image类型去存二进制流,方便你序列化和反序列化。或者直接存文件字符串进去。
1、在sql sever中建表时,数据类型选择 image 数据类型时,长度不能改变,只能为16,这是不是太小了啊?如果存储文件较大怎么办啊?
2、
rs->Fields->GetItem(/*IMAGE字段*/)->AppendChunk(varBLOB);
这段话中,
rs是这样 _RecordsetPtr rs 定义的吗?
再就是怎么确定是哪个表呢?连接数据库只能是连接数据库,不能确定是哪个表啊。假如我的表的名称是record,字段名称是filecontent,
调用时写成record.filecontent可以吗?
BLOB 数据在 SQL Server 数据库中主要由 IMAGE 类型体现,最大容量为 2GB 。其存储方式不同于普通的数据类型,对于普通类型的数据系统直接在用户定义的字段上存储数据值,而对于 IMAGE 类型数据,系统开辟新的存储页面来存放这些数据,表中 IMAGE 类型数据字段存放的仅是一个 16 字节的指针,该指针指向存放该条记录的 IMAGE 数据的页面。
rs是这样 _RecordsetPtr rs 定义的吗
是
再就是怎么确定是哪个表呢?void OnRecordsetAddnew()
{
_RecordsetPtr pRS; HREFTYPE hr = NOERROR; _bstr_t bstrQuery("SELECT * FROM [record] WHERE myID IS NULL"); //假设myID是主键 ,这里打开一个不包含记录的记录集 _variant_t vtNULL; vtNULL.vt = VT_ERROR;
vtNULL.scode = DISP_E_PARAMNOTFOUND;
try
{
hr = pRS.CreateInstance(__uuidof(Recordset));
if(SUCCEEDED(hr))
{
pRS->PutRefActiveConnection(m_pConnection); //m_pConnection 是以打开的 _ConnectionPtr 变量
hr = pRS->Open(_variant_t(bstrQuery),
vtNULL,
adOpenForwardOnly,
adLockOptimistic,
adCmdText);
if (SUCCEEDED(hr))
{
//方案1
//字段名list
COleSafeArray vaFieldList;
vaFieldList.CreateOneDim(VT_VARIANT,2); //假设有2个字段
LONG larrayIndex[1];
//ID字段名
larrayIndex[0] = 0;
vaFieldList.PutElement(larrayIndex,&(_variant_t("myID")));
//filecontent字段名
larrayIndex[0] = 1;
vaFieldList.PutElement(larrayIndex,&(_variant_t("filecontent")));
//字段的值list
COleSafeArray vaValueList;
vaValueList.CreateOneDim(VT_VARIANT,2);
//ID值
larrayIndex[0] = 0;
vaValueList.PutElement(larrayIndex,&(_variant_t("001"));
//filecontent字段值
larrayIndex[0] = 1;
vaValueList.PutElement(larrayIndex,&varBLOB)); //varBLOB 是 7楼 代码的 _variant_t varBLOB;
pRS->AddNew(vaFieldList,vaValueList);
pRS->Close();
//方案2
// pRS->AddNew();
// pRS->PutCollect("myID",_variant_t("001"));
// pRS->Fields->GetItem("filecontent")->AppendChunk(varBLOB);//varBLOB 是 7楼 代码的 _variant_t varBLOB;
// pRS->Update();
// pRS->Close();
}
}
}
catch(_com_error & e)
{
TRACE("Error : %081x. \n",e.Error());
TRACE("ErrorMessage : %s. \n",e.ErrorMessage());
TRACE("Source : %s. \n",(LPCTSTR)_bstr_t(e.Source()));
TRACE("Description : %s. \n",(LPCTSTR)_bstr_t(e.Description())); }
catch(...)
{
TRACE("\n *** Unhandled Exception *** \n");
}
}
但是在运行7楼大哥的代码时报错了,是Runtime Error. 请问是怎么回事
也可以改成
pRS->PutCollect("filecontent",varBLOB); // pRS->Update() 后释放空间 SAFEARRAY
::SafeArrayDestroyData(psa);//从数据库获取数据
_variant_t data = pRS->GetCollect("filecontent");
if(::GetFileAttributes(name)!=-1) //name 是你的文件名
::SetFileAttributes(name,FILE_ATTRIBUTE_NORMAL);//保存到文件
CFile file;
if(file.Open(name,CFile::modeCreate|CFile::modeWrite))
{
file.WriteHuge(data.parray->pvData,data.parray->rgsabound[0].cElements);
file.Close();
}