Read binary data from SQL Server
-
Hello. I have a _CommandPtr that has the type CommandTypeEnum::adCmdTex, and the CommandText a query("Select test from Table_1") and this select returns one row and one column that has a binary data(image) in it.
CommandPtr pCommand; //Create the C++ ADO Command Object pCommand.CreateInstance(__uuidof(Command)); pCommand->ActiveConnection = this->pConnection; //Make the ADO C++ command object to accept stored procedure pCommand->CommandType = CommandTypeEnum::adCmdText; //Tell the name of the Stored Procedure to the command object pCommand->CommandText = _bstr_t("select test from Table_1"); //get recordset pRecordset = pCommand->Execute(NULL,NULL,CommandTypeEnum::adCmdText); BYTE* buffer = NULL; if(pRecordset != NULL) { while (!pRecordset->GetEndOfFile()) { VARIANT var = pRecordset->Fields->GetItem("test")->Value; void * pData = NULL; SafeArrayAccessData(var.parray, &pData); long size = GetArraySize(var, NULL); buffer = new BYTE[size]; memcpy(buffer, pData, size); SafeArrayUnaccessData(var.parray); pRecordset->MoveNext(); } pRecordset->Close(); }
wherelong GetArraySize(const VARIANT& var, long * nElems) { if ( !(var.vt & VT_ARRAY) ) return -1; long size = 0; long dims = SafeArrayGetDim(var.parray); long elemSize = SafeArrayGetElemsize(var.parray); long elems = 1; for ( long i=1; i <= dims; i++ ) { long lbound, ubound; SafeArrayGetLBound(var.parray, i, &lbound); SafeArrayGetUBound(var.parray, i, &ubound); elems *= (ubound - lbound + 1); } if ( nElems ) *nElems = elems; size = elems*elemSize; return size; }
When I debug the application, I get the record in the VARIANT var = pRecordset->Fields->GetItem("test")->Value; but when I put par.parray in Memory explorer in VS, i only see this data "fe ee fe ee fe ee fe ee fe ee fe ee fe ee ...fe ee" and of course it brakes at SafeArrayGetLBound(var.parray, i, &lbound); Can someone tell me where I am doing a very bad thing? P.S. I was able to read the binary data correctly from the server using C#.NET 2.0.Eusebiu
-
Hello. I have a _CommandPtr that has the type CommandTypeEnum::adCmdTex, and the CommandText a query("Select test from Table_1") and this select returns one row and one column that has a binary data(image) in it.
CommandPtr pCommand; //Create the C++ ADO Command Object pCommand.CreateInstance(__uuidof(Command)); pCommand->ActiveConnection = this->pConnection; //Make the ADO C++ command object to accept stored procedure pCommand->CommandType = CommandTypeEnum::adCmdText; //Tell the name of the Stored Procedure to the command object pCommand->CommandText = _bstr_t("select test from Table_1"); //get recordset pRecordset = pCommand->Execute(NULL,NULL,CommandTypeEnum::adCmdText); BYTE* buffer = NULL; if(pRecordset != NULL) { while (!pRecordset->GetEndOfFile()) { VARIANT var = pRecordset->Fields->GetItem("test")->Value; void * pData = NULL; SafeArrayAccessData(var.parray, &pData); long size = GetArraySize(var, NULL); buffer = new BYTE[size]; memcpy(buffer, pData, size); SafeArrayUnaccessData(var.parray); pRecordset->MoveNext(); } pRecordset->Close(); }
wherelong GetArraySize(const VARIANT& var, long * nElems) { if ( !(var.vt & VT_ARRAY) ) return -1; long size = 0; long dims = SafeArrayGetDim(var.parray); long elemSize = SafeArrayGetElemsize(var.parray); long elems = 1; for ( long i=1; i <= dims; i++ ) { long lbound, ubound; SafeArrayGetLBound(var.parray, i, &lbound); SafeArrayGetUBound(var.parray, i, &ubound); elems *= (ubound - lbound + 1); } if ( nElems ) *nElems = elems; size = elems*elemSize; return size; }
When I debug the application, I get the record in the VARIANT var = pRecordset->Fields->GetItem("test")->Value; but when I put par.parray in Memory explorer in VS, i only see this data "fe ee fe ee fe ee fe ee fe ee fe ee fe ee ...fe ee" and of course it brakes at SafeArrayGetLBound(var.parray, i, &lbound); Can someone tell me where I am doing a very bad thing? P.S. I was able to read the binary data correctly from the server using C#.NET 2.0.Eusebiu
I found the solution... it's the GetChunck method....
if(pRecordset != NULL) { while (!pRecordset->GetEndOfFile()) { ADO_LONGPTR size = pRecordset->Fields->Item["test"]->ActualSize; BYTE* buffer = new BYTE[size]; _variant_t varChunk; varChunk = pRecordset->Fields->Item["test"]->GetChunk(size); BYTE * pData = NULL; SafeArrayAccessData(varChunk.parray, (void HUGEP* FAR*)&pData); memcpy(buffer, pData, size); SafeArrayUnaccessData(varChunk.parray); ofstream myFile ("C:\\Blue hills.jpg", ios::out | ios::binary); myFile.write((char*)buffer, size); myFile.flush(); pRecordset->MoveNext(); } pRecordset->Close(); }
Eusebiu