1. 程式人生 > >C++ 讀取影象(二進位制)儲存到mysql blob

C++ 讀取影象(二進位制)儲存到mysql blob

以下程式碼不能直接執行,MySqlDB類沒有給出,使用的是mysqlconncpp連線mysql。

#include "MySqlDB.h"

#include <zlib.h>
#include <lzlib.h>

class DataBuf : public std::streambuf
{
public:
    DataBuf(char* d, size_t s)
    {
        setg(d, d, d+s);
    }
};

int main()
{
    FILE* f = fopen("think.jpg","rb");//二進位制方式讀取圖片

    char buf[1024*50]={0};
    int len = fread(buf,sizeof(char),1024*50,f);

    Buffer c_buf(len);
    unsigned long int zinlen = c_buf.capacity();
    compress((Bytef*)c_buf.wr_ptr(),&zinlen,(Bytef*)buf,len);//zip壓縮二進位制資料
    c_buf.wr_ptr(zinlen);


    MySqlDB* db = new MySqlDB();
    int ret = db->init("127.0.0.1",3306,"poker","mysql","mysql123");
    if( ret <0 )
    {
        return 0;
    }
    db->save_pic(1,zinlen,c_buf.rd_ptr());//儲存到資料庫(函式實現在後面)


    Buffer buffer(100*1024);
    db->load_pic(1,&buffer);//從資料庫載入(函式實現在後面)

    Buffer z_out(len);
    unsigned long int zoutlen = z_out.capacity();
    uncompress((Bytef*)z_out.wr_ptr(),&zoutlen,(Bytef*)buffer.rd_ptr(),buffer.total_len());//解壓
    z_out.wr_ptr(zoutlen);

    FILE* fout = fopen("think1.jpg","wb");//以二進位制方式開啟新的檔案 命名為 think1.jpg

    while(len>0)
    {
        int wlen = fwrite(z_out.rd_ptr(),sizeof(char),z_out.total_len(),fout);//寫入,此時 think1.jpg 和think.jpg一樣
        len -=wlen;
    }
    return len;

}

//儲存資料到資料庫

int MySqlDB::save_pic(int role_id,const int len,char* ptr)
{
    if(NULL == ptr)
    {
        return 0;
    }

    TRY
        MyConnection conn = this->get_conn();
        if (NULL == conn.m_conn)
        {
            return ERROR_SERVER_PROBLEM;
        }

        std::string table_name = "account";

//sql語句的組裝
        std::stringstream s_head,s_tail;
        s_head << "update "<< table_name << " set ";
        std::string sql = s_head.str()+" image=? where roleid=? limit 1";

        DataBuf buffer(ptr,len);
        std::istream str(&buffer);
        PreparedStatement *pstmt = conn.m_conn->prepareStatement(sql);
        pstmt->setBlob(1, &str);//設定blob
        pstmt->setInt(2,role_id);

        int result = pstmt->executeUpdate();
        if (result < 0)
        {
            return ERROR_SERVER_PROBLEM;
        }
        this->destory(NULL, pstmt);
        return 0;
    //CATCH(-1)
    }catch (SQLException& e)    {
        char log[10000]={0};
        sprintf(log,"ErrorCode:[%d],SQLState:[%s] description:[%s]",
                e.getErrorCode(),e.getSQLState().c_str(),e.what());
        std::cout << log << std::endl;
                return -1;
    }
    return 0;
}

//從資料庫載入

int MySqlDB::load_pic(int role_id,Buffer* mb)
{
    TRY
        MyConnection conn = this->get_conn();
        if (NULL == conn.m_conn)
        {
            return ERROR_SERVER_PROBLEM;
        }
        sql::Statement *state = conn.m_conn->createStatement();
        if (NULL == state)
        {
            return ERROR_SERVER_PROBLEM;
        }
        std::string table_name =  "account";

        std::string sql = "select image from %s where roleid=%d;";
        char sql_query[512] = { 0 };
        sprintf(sql_query, sql.c_str(), table_name.c_str(), 1);

        ResultSet *rs = state->executeQuery(sql_query);
        if (NULL == rs || rs->rowsCount() <= 0)
        {
            this->destory(rs, state);
            return ERROR_SERVER_PROBLEM;
        }

        if (rs->next())
        {
            std::istream *image = rs->getBlob("image");
            image->seekg(0, std::ios_base::end);
            size_t size = image->tellg();//獲取長度
            image->seekg(0, std::ios_base::beg);

            image->read(mb->wr_ptr(), size);//讀取到自己的快取中
            mb->wr_ptr(size);
            DELETE_PTR(image);
        }
        this->destory(rs, state);
        return 0;
    CATCH(-1)
    return 0;
}