我正在研究VC ++ cli应用程序,我需要将图像存储到MySql数据库中。我意识到这通常不是一个好习惯,但由于访问文件系统的限制,这是我必须要去的方式。
所以我已经能够将图像放入托管的unsigned char数组中,这看起来就像我在网上找到的例子中所做的那样(主要是在C#中包含不可用的命令)。我只需要弄清楚如何将它放入数据库中,我很茫然,而且我的搜索还没有发现VC ++至少有用的东西。
这是我需要做的,我有一个托管数组:
array<unsigned char>^ imageSource;
包含使用以下内容的图像字节:
System::IO::FileStream^ fs;
System::IO::BinaryReader^ br;
//Read the Image
fs = gcnew System::IO::FileStream(filepath, System::IO::FileMode::Open, System::IO::FileAccess::Read);
br = gcnew System::IO::BinaryReader(fs);
//Store the Image into an array
imageSource = br->ReadBytes((int)fs->Length);
接下来我需要将其保存到我的数据库中:
sql::Connection *sqlConn;
sql::PreparedStatement *sqlStmt;
sql::ResultSet *sqlResult;
// Sql Connection Code
//I have a Routine to save images
//and have Select because get_last_insert_id() is not available in the c++ connector
sqlStr = "SELECT save_item_image (?, ?, ?, ?, ?) AS ID";
//Prepare the Query
sqlStmt = this->sqlConn->prepareStatement(sqlStr);
//Set Parameters in SqlStatment
sqlStmt->setInt(1, 1);
sqlStmt->setInt(2, 1);
sqlStmt->setBlob(3, &imgSource); <-- This is where I need to insert image
sqlStmt->setString(4, "jpg");
sqlStmt->setString(5, "test.jpg");
sqlStmt->executeUpdate();
据我所知,setBlob函数需要std :: istream来读取数据。我不知道该怎么做,这是我的主要挂断。
答案 0 :(得分:0)
我终于弄清楚了这一点,并希望发布一个答案,以防其他人正在寻找答案。
实现此目的的最简单方法是使用pin_ptr引用托管数组中的第一个元素,该元素实际上是指向整个数组的指针。接下来我们转换为另一个指针,最后转换为char *指针。最后,为了在setBlob中使用它,我们需要为istream创建一个内存缓冲区。
这是一个有效的例子:
array<unsigned char>^ rawImageData;
System::IO::FileStream^ fs;
System::IO::BinaryReader^ br;
//Setup the filestream and binary reader
fs = gcnew System::IO::FileStream(filepath, System::IO::FileMode::Open, System::IO::FileAccess::Read);
br = gcnew System::IO::BinaryReader(fs);
//Store the Image into a byte array
rawImageData = br->ReadBytes((int)fs->Length);
#include <iostream>
#include <istream>
#include <streambuf>
#include <string>
struct membuf : std::streambuf {
membuf(char* begin, char* end) {
this->setg(begin, begin, end);
}
};
sql::Driver *sqlDriver;
sql::Connection *sqlConn;
sql::PreparedStatement *sqlStmt;
sql::ResultSet *sqlResult;
/*** SQL Connection Code Here ***/
//Build the Item Sql String to Save Images
sqlStr = "SELECT save_item_image (?, ?, ?, ?, ?) AS ID";
//Prepare the Query
sqlStmt = sqlConn->prepareStatement(sqlStr);
//Create a pin_ptr to the first element in the managed array
pin_ptr<unsigned char> p = &rawImageData[0];
//Get a char pointer to use in the memory buffer
unsigned char* pby = p;
char* pch = reinterpret_cast<char*>(pby);
//Memory Buffer, note the use of length from the RawImageData, images contain
//NULL char's so size_of doesn't return the right length.
membuf sbuf(pch, pch + rawImageData->Length);
//Create the istream to use in the setBlob
std::istream sb(&sbuf, std::ios::binary | std::ios::out);
//Finally save everything into the database
sqlStmt->setInt(1, 1);
sqlStmt->setInt(2, 1);
sqlStmt->setBlob(3, &sb); //*** Insert the Image ***/
sqlStmt->setString(4, "Name");
sqlStmt->setString(5, "Path");
sqlStmt->executeUpdate();
sqlResult = sqlStmt->getResultSet();
//Make sure everything was executed ok
if (sqlResult->rowsCount() > 0) {
sqlResult->next();
int image_id = sqlResult->getInt("ID");
}
注意:我在sql字符串中使用了SELECT,因为save_item_image实际上是一个返回插入图像id的函数。我需要使用这种方法,因为没有其他方法可以获得最后插入的ID(我能找到)在C ++连接器中。在其他MySql库中,有一个last_insert_id()命令,但不在连接器中。