_bstr_t m_strSQL = _T("SELECT Photo FROM CorpEmp WHERE EmpName='") + v_strEmpName + _T("' AND EmpNamePY='") + v_strEmpNamePY + _T("'");
try
  {
    // 使用ADO创建数据库记录集
    ado.m_pRecordset.CreateInstance(__uuidof(Recordset));
    ado.m_pRecordset->Open((_variant_t)m_strSQL, _variant_t((IDispatch*)ado.m_pConnection, true), adOpenStatic, adLockOptimistic, adCmdText);
    // 判断记录是否为空
    if(!ado.m_pRecordset->adoBOF && !ado.m_pRecordset->adoEOF)
    {
      // 如果不为空,则检查 Photo 是否为空
      lDataSize = ado.m_pRecordset->GetFields()->GetItem("Photo")->ActualSize;
      if(lDataSize > 0)
      {
        // 需要绘图
        pStm.CreateInstance(_T("ADODB.Stream"));
        variant_t varOptional(DISP_E_PARAMNOTFOUND, VT_ERROR);
        pStm->PutType(adTypeBinary);// 类型为二进制
        // 得到字段内容的大小
        // m_pRecordset为一个打开的纪录集对象,含有Photo这个blob字段
        pStm->Open( varOptional, adModeUnknown, adOpenStreamUnspecified, _bstr_t(), _bstr_t());
        // 打开 pStm
        pStm->Write(_variant_t(ado.m_pRecordset->GetFields()->GetItem(_T("Photo"))->Value));
        varBLOB = pStm->Read(adReadAll);
        // 把 Photo 字段的内容写入pStm
        pStm->SaveToFile(_T("pub.jpg"), adSaveCreateOverWrite);// 不知道为什么,这行代码不能去掉,否则 pStm 不正常
        // 以下代码用于作图
        HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, pStm->GetSize());
        LPVOID pvData = NULL;
        if (hGlobal != NULL)
        {
          if ((pvData = GlobalLock(hGlobal)) != NULL)
          {
            char * m_pBMPBuffer = new char[pStm->GetSize()+1];//分配必要的存储空间
            char *pBuf = NULL;
            SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
            memcpy(pvData,pBuf,pStm->GetSize()); // 每次执行到这里出错,提示访问内存冲突            SafeArrayUnaccessData (varBLOB.parray);
            GlobalUnlock(hGlobal);
          }
          c_EmpPhoto.Load(hGlobal, pStm->GetSize());
          GlobalFree(hGlobal);
          c_EmpPhoto.Draw();
          Invalidate();
          // 作图完成
        }
      }
    }
    if(ado.m_pRecordset != NULL)
      ado.m_pRecordset->Close();
  }
// 捕捉异常
catch (_com_error e)
{
#ifdef _DEBUG
  CATCH_ERROR;
#endif
#ifdef _RELEASE
  AfxMessageBox(e.Description());
#endif
  return FALSE;
}

解决方案 »

  1.   

    memcpy(pvData,pBuf,pStm->GetSize());
    看看pvData的空间是否小于pStm->GetSize(),或pvData是否为空?
      

  2.   

    SafeArrayAccessData(varBLOB.parray,(void **)&pBuf);
    memcpy(pvData,pBuf,pStm->GetSize()); ---
    check to see whether pBuf is invalid? 
    check result of pStm->GetSize(),or try GetChunk
    where to SafeArrayCreate?
      

  3.   

    其一:varBLOB = pStm->Read(adReadAll);执行到这句后,varBLOB的值仍为VT_NULL;
    其二:开辟内存问题,把一段缓冲区问题用memcpy给pvData,导致出错!
    关于这段代码是也是参考网上利用_ISteamPtr接口来写BLOB对象在数据库中的读写的,其中pStm就是_ISteamPtr接口的实例化。这段代码有时正常,有时不正常,其中pStm->SaveToFile(_T("pub.jpg"), adSaveCreateOverWrite);这一句如果去掉就肯定出问题,不知道是什么原因!
      

  4.   

    看代码,pvData 空间:
    HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, pStm->GetSize());
    LPVOID pvData = NULL;pBuf 空间:
    char * m_pBMPBuffer = new char[pStm->GetSize()+1];//分配必要的存储空间
    char *pBuf = NULL;
      

  5.   

    感觉用GetChunk函数还容易点,之所以采用_ISteamPtr接口,主要是考虑可能有不同格式,同时需要导出文件。令人奇怪的是调用pStm->Write()之后,为什么还一定要调用pStm->SaveToFile(),难道我不导出文件也不行吗?
      

  6.   

    给你一段我的CPicture中保存VARIANT==>IPicture的代码,你参考一下
    我这里的IStream 是系统自带的那个与ADO.Stream有些不一样
    //
    我的习惯是直接用IPicture取出绘图.    // 字节流
        CPicture& operator = ( VARIANT& var )
        {
            Release();
            if( var.vt == VT_UNKNOWN && var.punkVal != NULL )
                var.punkVal->QueryInterface( IID_IPicture, (void**)&m_pp );
            else if( var.vt == VT_DISPATCH && var.pdispVal != NULL )
            {
                var.pdispVal->QueryInterface( IID_IPicture, (void**)&m_pp );
            }
            else if( ( var.vt & VT_ARRAY ) && (var.parray != NULL ) )
            {
                LONG lSize = ::SafeArrayGetElemsize( var.parray );
                CreateFromVariant( var, lSize );
            }
            //
            return *this;
        }    BOOL CreateFromVariant( VARIANT& var , LONG lSize )
        {
            HRESULT         hr = S_OK;
            HGLOBAL         hGb = NULL;
            IStreamPtr      spStream;
            ULARGE_INTEGER  uls;        Close();
            //
            if( CreateStreamOnHGlobal( NULL, TRUE,&spStream) != S_OK )
                return FALSE;        uls.QuadPart = ULONGLONG( lSize+1 );        if( FAILED( spStream->SetSize( uls ))) return FALSE;         if( FAILED( GetHGlobalFromStream( spStream, &hGb )) || 
                hGb == NULL ) return FALSE;
            
    BYTE* datap = (BYTE*)GlobalLock( hGb );
            for( LONG i =0; i < lSize ; i++ )
            {
                hr = SafeArrayGetElement( var.parray, &i, datap++ );
                if( FAILED( hr ) )
                {
                    break;
                }
            }
            GlobalUnlock( hGb );        Release();
            return ( (FAILED(::OleLoadPicture( spStream , 0, 0, IID_IPicture, (LPVOID *)&m_pp))) ? FALSE : TRUE);
        }