在MySql数据库中VC ++存储数组<unsigned char =“”> ^

时间:2017-01-26 21:25:51

标签: mysql image visual-c++ c++-cli

我正在研究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来读取数据。我不知道该怎么做,这是我的主要挂断。

1 个答案:

答案 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);
    }
};

最后是MySQL代码:

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()命令,但不在连接器中。