我想用Access数据库保存jpg图片,怎么存?我怎么读呢?用ADO

ahr 2003-01-08 06:28:52
我想用Access数据库保存jpg图片,怎么存?我怎么读呢?用ADO
...全文
144 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
用户 昵称 2003-01-08
  • 打赏
  • 举报
回复
//下面执行外部程序,Word会自动启动并打开tyj.doc} }

catch(CExceptionpE)

{ pE-〉ReportError();

pE-〉Delete();

return; }

在按键“更新word文档”的Function中加入以下程序代码:

m_pSet-〉Edit(); // 声明编辑当前记录

UpdateData(TRUE);

CFile fileword;

CFileStatus fileStatus;

CString fileLocate;

static char BASED_CODE szFilter[] = "WORD Files (.doc)|.doc||";

// 下面将弹出典型的打开文件对话框,您可以选择任何目录下的.doc文件

CFileDialog dlg(TRUE,NULL,NULL,0,szFilter,this);

if(dlg.DoModal()= =IDOK)

fileLocate=dlg.GetPathName();

else

fileLocate="";

if(fileLocate= ="")

AfxMessageBox("您没选文件");

else{

fileword.Open(fileLocate,CFile::modeRead);

fileword.GetStatus(fileStatus);

m_pSet-〉m_REPORT.m_dwDataLength=fileStatus.m_size;

HGLOBAL hGlobal = GlobalAlloc(GPTR,fileStatus.m_size);

m_pSet-〉m_REPORT.m_hData = GlobalLock(hGlobal);

fileword.ReadHuge(m_pSet-〉m_REPORT.m_hData,fileStatus.m_size);

//把您选择的文件的数据写入m_pSet-〉m_REPORT

m_pSet-〉SetFieldDirty(&&m_pSet-〉m_REPORT);

m_pSet-〉SetFieldNull(&&m_pSet-〉m_REPORT,FALSE);

m_pSet-〉Update(); // 更新记录

GlobalUnlock(hGlobal); }

上述代码只要稍做修改,即可把Execl等各类文件存入数据库中。对应按键“新增word文档”只需要复制“更新Word文档”中的代码,并把m_pSet-〉Edit();换成m_pSet-〉AddNew();即可。完成上述步骤后,打开abc.cpp,把RUNTIME_CLASS(CAbcView));这句换成RUNTIME_CLASS(CReportFormView)); 这样程序启动时就显示了该FormView。
用户 昵称 2003-01-08
  • 打赏
  • 举报
回复
在用Visual C++编写应用程序时,常会遇到如何存取数据库中大对象的问题。大对象文档以二进制数据形式保存在BLOB类型的字段中,这些大对象可能是Word、Execl或图片文件等,目前多数数据库都支持BLOB类型的字段。

VC存取这些大对象数据有众多方法,如OLE、ActiveX等,事实上VC的MFC提供了一个很方便的实现方法,即利用MFC提供的CLongBinary类可以方便地实现存取BLOB字段。下面笔者将举例说明。

首先用以下SQL语句建一个含BLOB字段的数据表:

CREATE TABLE REPORTTABLE(REGISTERNUM CHAR(12) NOT NULL,REPORT BLOB(5M),PRIMARY KEY(REGISTERNUM));

建完该表后,配置好ODBC数据源,设定数据源名为ABCDB。

我们用VC的MFC AppWizard建一个新的Project,设定项目名为ABC,下一步选Single Document,在提示你想包含什么样的数据库支持时,选Header files only,然后完成建立。

接着在Resources的Dailog资源中新建一个FormView,打开该FormView,启用ClassWizard,建立一个新类,设定类名叫CReportRecordSet,Base Class选CRecordSet,然后选ABCDB为数据源,再选择表REPORTTABLE,启动ClassWizrd,并建立新类CReportFormView,Base Class为CRecordView,选Recordset时,选CReportRecordSet。

打开ReportRecordSet.h,找到该行:CString m_REPORT; 改为CLongBinary m_REPORT;这样程序就知道m_REPORT是和BLOB字段交换数据。同样,我们还需要修改另外几处,打开ReportRecordSet.cpp后,删除m_REPORT = _T("");一句。再找到RFX_Text(pFX, _T("[REPORT]"), m_REPORT);一句,将其改为RFX_LongBinary(pFX, _T("[REPORT]"), m_REPORT); ODBC方法存取数据库时使用RFX_LongBinary;DAO方法则用DFX_LongBinary。

再次打开FormView,添加一个Edit控件,并用ClassWizard将它和member variable m_pSet-〉m_ REGISTERNUM关联,然后在FormView上增加三个按键,Caption名分别叫“取得Word文档”、“更新word文档”、“新增word文档”。并分别为这三个按键建立各自的Function,然后我们为这三个按键增加相应的代码。在按键“取得Word文档”的Function中加入如下代码:

try //该程序的所在当前目录是e:\qc\abc\

{ if (m_pSet-〉IsEOF())

AfxMessageBox("没有该小组的成果报告");

else {//下面检测临时文件tyj.doc是否存在

HANDLE hFind;

WIN32_FIND_DATA findData = {0};

hFind=FindFirstFile("e:\\qc\\abc\\tyj.doc",&&findData);

// FindFirstFile是Windows API 函数

if(hFind = = INVALID_HANDLE_VALUE)

AfxMessageBox("不存在临时文件");

else

{AfxMessageBox("有临时文件");

DeleteFile("e:\\qc\\abc\\tyj.doc");

//利用API函数删除该临时文件

}

CString strFileName="e:\\qc\\abc\\tyj.doc";

CFile outFile(strFileName,CFile::modeCreate|CFile::modeWrite);

//modeCreate指示构造函数创建一个新文件

//下面这段把已经在内存中的BLOB字段数据内容写到临时生成的文件tyj.doc中

LPSTR buffer = (LPSTR)GlobalLock(m_pSet-〉m_REPORT.m_hData);

outFile.WriteHuge(buffer,m_pSet-〉m_REPORT.m_dwDataLength);

GlobalUnlock(m_pSet-〉m_REPORT.m_hData);

outFile.Close();

ShellExecute(NULL,NULL,_T("tyj.doc"),NULL,_T("e:\\qc\\abc\\"),NULL);
arvid_gs 2003-01-08
  • 打赏
  • 举报
回复

// Temporarily add new publisher to table to avoid error due
// to foreign key constraint.
pConnection->Execute("INSERT publishers(pub_id) VALUES('" +
strPubID + "')",NULL,adCmdText);

pRstPubInfo->AddNew();
pRstPubInfo->Fields->GetItem("pub_id")->PutValue(strPubID);
pRstPubInfo->Fields->GetItem("pr_info")->
PutValue(pubrs.m_sz_prinfo);

//Assign the Safe array to a variant.
varChunk.vt = VT_ARRAY|VT_UI1;
varChunk.parray = psa;
hr = pRstPubInfo->Fields->GetItem("logo")->
AppendChunk(varChunk);

//Update the table
pRstPubInfo->Update();

lngLogoSize = pRstPubInfo->Fields->Item["logo"]->ActualSize;

//Show the newly added record.
printf("New Record : %s\nDescription : %s\nLogo Size : %s\n",
pubrs.m_sz_pubid,
pubrs.m_sz_prinfo,(LPCSTR)(_bstr_t)pRstPubInfo->Fields->
Item["logo"]->ActualSize);

//Delete new records because this is demonstration.
pConnection->Execute("DELETE FROM PUB_INFO WHERE pub_id = '"
+ strPubID +"'",NULL,adCmdText);

pConnection->Execute("DELETE FROM publishers WHERE pub_id = '"
+ strPubID +"'",NULL,adCmdText);

pRstPubInfo->Close();
pConnection->Close();
}
catch(_com_error &e)
{
// Notify the user of errors if any.
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());

PrintProviderError(pConnection);
printf("Source : %s \n Description : %s\n",
(LPCSTR)bstrSource,(LPCSTR)bstrDescription);
}
}

///////////////////////////////////////////////////////////
// //
// PrintProviderError Function //
// //
///////////////////////////////////////////////////////////

void PrintProviderError(_ConnectionPtr pConnection)
{
// Print Provider Errors from Connection object.
// pErr is a record object in the Connection's Error collection.
ErrorPtr pErr = NULL;
long nCount = 0;
long i = 0;

if( (pConnection->Errors->Count) > 0)
{
nCount = pConnection->Errors->Count;
// Collection ranges from 0 to nCount -1.
for(i = 0; i < nCount; i++)
{
pErr = pConnection->Errors->GetItem(i);
printf("\t Error number: %x\t%s", pErr->Number,
(LPCSTR) pErr->Description);
}
}
}

AppendChunkX.h:

#include "icrsint.h"

//This Class extracts pubid,prinfo.

class CPubInfoRs : public CADORecordBinding
{
BEGIN_ADO_BINDING(CPubInfoRs)

ADO_VARIABLE_LENGTH_ENTRY2(1, adVarChar, m_sz_pubid,
sizeof(m_sz_pubid), l_pubid, TRUE)

ADO_VARIABLE_LENGTH_ENTRY2(3, adVarChar, m_sz_prinfo,
sizeof(m_sz_prinfo), l_prinfo, TRUE)

END_ADO_BINDING()

public:
CHAR m_sz_pubid[10];
ULONG l_pubid;
CHAR m_sz_prinfo[200];
ULONG l_prinfo;

};
arvid_gs 2003-01-08
  • 打赏
  • 举报
回复
同意楼上的,给你VC的代码;
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" \
no_namespace rename("EOF", "EndOfFile")

#define ChunkSize 100

#include <ole2.h>
#include <stdio.h>
#include "conio.h"
#include "malloc.h"
#include "AppendChunkX.h"

//Function declarations
inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};
void AppendChunkX(void);
void PrintProviderError(_ConnectionPtr pConnection);

///////////////////////////////////////////////////////////
// //
// Main Function //
// //
///////////////////////////////////////////////////////////
void main()
{
if(FAILED(::CoInitialize(NULL)))
return;

AppendChunkX();

::CoUninitialize();
}

///////////////////////////////////////////////////////////
// //
// AppendChunkX Function //
// //
///////////////////////////////////////////////////////////
void AppendChunkX(void)
{
// Define ADO object pointers.
// Initialize pointers on define.
// These are in the ADODB:: namespace.
_RecordsetPtr pRstPubInfo = NULL;
_ConnectionPtr pConnection = NULL;

//Define other variables
//Interface Pointer declared.(VC++ Extensions)
IADORecordBinding *picRs = NULL;
CPubInfoRs pubrs; //C++ class object

HRESULT hr = S_OK;
_bstr_t strCnn("Provider=sqloledb;Data Source=srv;"
"Initial Catalog=Pubs;User Id=sa;Password=;");

_bstr_t strMessage,strPubID,strPRInfo;
_variant_t varChunk;
long lngOffSet,lngLogoSize;
char pubId[50];
lngOffSet = 0;

UCHAR chData;
CHAR ch;
SAFEARRAY FAR *psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = ChunkSize;

try
{
//Open a Connection.
TESTHR(pConnection.CreateInstance(__uuidof(Connection)));
TESTHR(pConnection->Open(strCnn,"","",NULL));

TESTHR(hr= pRstPubInfo.CreateInstance(__uuidof(Recordset)));

pRstPubInfo->CursorType = adOpenKeyset;
pRstPubInfo->LockType = adLockOptimistic;

TESTHR(pRstPubInfo->Open("pub_info",
_variant_t((IDispatch*)pConnection,true),
adOpenKeyset,adLockOptimistic,adCmdTable));

//Open an IADORecordBinding interface pointer which we'll use
//for Binding Recordset to a class
TESTHR(pRstPubInfo->QueryInterface(
__uuidof(IADORecordBinding),(LPVOID*)&picRs));

//Bind the Recordset to a C++ Class here
TESTHR(picRs->BindToRecordset(&pubrs));

//Display the available logos here
strMessage = "Available logos are: " + (_bstr_t)"\n\n";
printf(strMessage);
int Counter = 0;
while(!(pRstPubInfo->EndOfFile))
{
printf("\n%s",pubrs.m_sz_pubid);
printf("\n%s",strtok(pubrs.m_sz_prinfo,","));

//Display 5 records at a time and wait for user to continue.
if (++Counter >= 5)
{
Counter = 0;
printf("\nPress any key to continue...");
getch();
}
pRstPubInfo->MoveNext();
}

//Prompt For a Logo to Copy
printf("\nEnter the ID of a logo to copy: ");
scanf("%s",pubId);
strPubID = pubId;

//Copy the logo to a variable in chunks
pRstPubInfo->Filter = "pub_id = '" + strPubID + "'";
lngLogoSize = pRstPubInfo->Fields->Item["logo"]->ActualSize;

//Create a safe array to store the array of BYTES
rgsabound[0].cElements = lngLogoSize;
psa = SafeArrayCreate(VT_UI1,1,rgsabound);

long index1 = 0;
while(lngOffSet < lngLogoSize)
{
varChunk = pRstPubInfo->Fields->
Item["logo"]->GetChunk(ChunkSize);

//Copy the data only up to the Actual Size of Field.
for(long index=0;index<=(ChunkSize-1);index++)
{
hr= SafeArrayGetElement(varChunk.parray,&index,&chData);
if(SUCCEEDED(hr))
{
//Take BYTE by BYTE and advance Memory Location
TESTHR(SafeArrayPutElement(psa,&index1,&chData));
index1++;
}
else
break;
}
lngOffSet = lngOffSet + ChunkSize;
}
lngOffSet = 0;

printf("Enter a new Pub Id: ");
scanf("%s",pubrs.m_sz_pubid);
strPubID = pubrs.m_sz_pubid;

printf("Enter descriptive text: " );
scanf("%c",&ch);
gets(pubrs.m_sz_prinfo);

ahr 2003-01-08
  • 打赏
  • 举报
回复
字段数据类型 是什么?我这里的access看不到二进制的选项!
prettywolf 2003-01-08
  • 打赏
  • 举报
回复
将字段设为OLE类型,不过积极你存入一幅很小的图片数据库文件的大小也会变得很大,我试过存入一幅200多k的JPG,结果成了13M,你还是这样吧,在数据库中保存图片的PATH,然后图片存在其他目录中。
microyzy 2003-01-08
  • 打赏
  • 举报
回复
AppendChunk 和 GetChunk 方法范例
该范例使用 AppendChunk 和 GetChunk 方法用其他记录中的数据填写图像字段。

Public Sub AppendChunkX()

Dim cnn1 As ADODB.Connection
Dim rstPubInfo As ADODB.Recordset
Dim strCnn As String
Dim strPubID As String
Dim strPRInfo As String
Dim lngOffset As Long
Dim lngLogoSize As Long
Dim varLogo As Variant
Dim varChunk As Variant

Const conChunkSize = 100

' 打开连接
Set cnn1 = New ADODB.Connection
strCnn = "Provider=sqloledb;" & _
"Data Source=srv;Initial Catalog=pubs;User Id=sa;Password=; "
cnn1.Open strCnn

' 打开 pub_info 表。
Set rstPubInfo = New ADODB.Recordset
rstPubInfo.CursorType = adOpenKeyset
rstPubInfo.LockType = adLockOptimistic
rstPubInfo.Open "pub_info", cnn1, , , adCmdTable

' 提示复制徽标。
strMsg = "Available logos are : " & vbCr & vbCr
Do While Not rstPubInfo.EOF
strMsg = strMsg & rstPubInfo!pub_id & vbCr & _
Left(rstPubInfo!pr_info, InStr(rstPubInfo!pr_info, ",") - 1) & _
vbCr & vbCr
rstPubInfo.MoveNext
Loop
strMsg = strMsg & "Enter the ID of a logo to copy:"
strPubID = InputBox(strMsg)

' 将徽标复制到大块中的变量。
rstPubInfo.Filter = "pub_id = '" & strPubID & "'"
lngLogoSize = rstPubInfo!logo.ActualSize
Do While lngOffset < lngLogoSize
varChunk = rstPubInfo!logo.GetChunk(conChunkSize)
varLogo = varLogo & varChunk
lngOffset = lngOffset + conChunkSize
Loop

' 从用户得到数据。
strPubID = Trim(InputBox("Enter a new pub ID:"))
strPRInfo = Trim(InputBox("Enter descriptive text:"))

' 添加新记录,将徽标复制到大块中。
rstPubInfo.AddNew
rstPubInfo!pub_id = strPubID
rstPubInfo!pr_info = strPRInfo

lngOffset = 0 ' 重置位移。
Do While lngOffset < lngLogoSize
varChunk = LeftB(RightB(varLogo, lngLogoSize - lngOffset), _
conChunkSize)
rstPubInfo!logo.AppendChunk varChunk
lngOffset = lngOffset + conChunkSize
Loop
rstPubInfo.Update

' 显示新添加的数据。
MsgBox "New record: " & rstPubInfo!pub_id & vbCr & _
"Description: " & rstPubInfo!pr_info & vbCr & _
"Logo size: " & rstPubInfo!logo.ActualSize

' 删除新记录,因为这只是演示。
rstPubInfo.Requery
cnn1.Execute "DELETE FROM pub_info " & _
"WHERE pub_id = '" & strPubID & "'"

rstPubInfo.Close
cnn1.Close

End Sub

microyzy 2003-01-08
  • 打赏
  • 举报
回复
Field.AppendChunk()保存二进制数据到数据库
Field.GetChunk()从数据库取二进制数据

16,471

社区成员

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

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

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