sql >> データベース >  >> RDS >> PostgreSQL

ClibpqでByteaバイナリデータを使用したPostgreSQLのファイルの保存と選択

    これは、コードが正常に機能した結果です。それが誰かを助けることができる場合に備えて、私は今それを投稿する時間があります。ビテアがどのように機能するかを理解するのは少し難しかったですが、最終的には解決しました。コミュニティに敬意を表します。

    #include <string>
    #include <fstream>
    #include <iostream>
    #include <sstream>
    
    #include "libpq/libpq-fs.h"
    #include "libpq-fe.h"
    
    #pragma comment(lib, "libpq.lib")   /*!< Only for windows compilation */
    
    int main(int argc, char* argv[])
    {
        ManageDB manager;       
    
        manager.conn = manager.ConnectDB();  // My manager, connects ok
    
        const char* fileName = {"test.png"};
        const char* fileNameOut = { "testOut.png" };
    
        FILE* file = fopen(fileName, "rb");
        if (file == NULL) cout << endl << "FILE WAS UNABLE TO BE READED" << endl;
        fseek(file, 0, SEEK_END);
        long int fileSize = ftell(file);
    
        rewind(file);
    
        unsigned char* buffRead = (unsigned char*)malloc(fileSize);
        size_t bytes_read = fread(buffRead, 1, fileSize, file);
        if (bytes_read != fileSize) cout << endl << "fread reading Error";
        fclose(file);
        
        size_t* sizeP = new size_t(fileSize);
    
        const char* paramValues[3];
        paramValues[0] = "1";
        paramValues[1] = fileName;
        paramValues[2] = reinterpret_cast<const char*>(buffRead);   // type cast required to PQexeParams
    
        const int paramFormats[3]{ 0,0,1 };   //0 = text, 1 = binary
        const int paramLenghts[3]{ strlen(paramValues[0]), strlen(paramValues[1]), fileSize};
    
        PGresult *res = PQexecParams(manager.conn, "INSERT INTO filebyte (id, filename, file) VALUES($1::text, $2::text, $3::bytea)",
            3,              /* params num */
            NULL,           /* let the backend deduce param type */
            paramValues,
            paramLenghts,
            paramFormats,
            1);
    
        if (res && PQresultStatus(res) == PGRES_COMMAND_OK) cout << endl << "Inserted data to filebyte OK";
    
        PQfreemem(res);
    
        //************************download from DB*************************
        
        const char* bytesFromDB = new const char[fileSize];
        int sizeR;
        // Table columns = id(text) | filename(text) | file(bytea)
        const char* sentenceEx = "SELECT file FROM filebyte WHERE id='1'";
    
        res = PQexec(manager.conn, sentenceEx);
    
        if (res && PQresultStatus(res) == PGRES_TUPLES_OK)
        {
            sizeR = PQgetlength(res, 0, 0);
            bytesFromDB = PQgetvalue(res, 0, 0);
        }
        else cout << endl << "Error at inserting file data in filebyte table";
    
        string hex(bytesFromDB, 2, sizeR-2);  //removing the first '\x' characters of the result.
    
        // vars for converting to real bytes process
        std::basic_string<uint8_t> bytes;
        bytes.clear();
        std::string nextbyte; 
        nextbyte.clear();
        uint16_t byte;
    
        // Iterate over every pair of hex values in the input string (e.g. "18", "0f", ...)
        for (size_t i = 0; i < hex.length(); i += 2)
        {
            // Get current pair and store in nextbyte
            nextbyte = hex.substr(i, 2);
    
            // Put the pair into an istringstream and stream it through std::hex for
            // conversion into an integer value.
            // This will calculate the byte value of your string-represented hex value.
            std::istringstream(nextbyte) >> std::hex >> byte;
    
            // As the stream above does not work with uint8 directly, we have to cast it now.
            // As every pair can have a maximum value of "ff",
            // which is "11111111" (8 bits), we will not lose any information during this cast.
            bytes.push_back(static_cast<uint8_t>(byte));
        }
    
        // string obj from bytes-"array"
        std::string result(begin(bytes), end(bytes));
    
        ofstream myFile(fileNameOut, ios::out | ios::ios_base::binary);
        
        if (myFile.is_open())
        {
            myFile << result;
            myFile.close();
        }
        else cout << endl << "Impossible to writte the file " << fileNameOut;
        
        manager.CloseConn(manager.conn);   //closes connection with database internally ok
    
        PQfreemem(res);
        free(buffRead);
        delete sizeP;
        free((char*)fileName[8]);
        free((char*)fileNameOut[11]);
        
        return true;
    }
    
    


    1. ORA-01537。ファイルが含まれている場所を検索したい

    2. XMLをSQLServerに解析します

    3. Androidアプリで外部データベースを使用できません

    4. 1つのSQLスクリプトで子と親の行を削除します