8. Linux C/C++ implements MySQL image insertion and image reading

This article combines Linux C/C++ to realize MySQL image insertion and image reading, especially the specific process of database reading and writing

1. File reading related functions

  • fseek() can move the file pointer to any position in the file. Its basic form is as follows:
int fseek(FILE *stream, long offset, int whence);

Among them, stream is a pointer to the file stream that has been opened; offset is the offset relative to the position indicated by the whence parameter, which can be positive, negative or zero; and whence specifies the relative offset indicated by the offset location sign. Specifically, it can take one of the following three values:
– SEEK_SET: means to calculate the offset from the beginning of the file;
– SEEK_CUR: means to calculate the offset from the current position; – SEEK_END: ​​means to calculate the offset from
the end of the file Start calculating the offset.
When the call is successful, the return value is 0; otherwise, a non-zero value is returned.
It should be noted that after using the fseek() function, we need to obtain the current file pointer position by calling the ftell() function, and ensure that the position is consistent with the position we want to set.

  • ftell() is a function used to obtain the current position of the file pointer, and its prototype is as follows:
long ftell(FILE *stream);

Among them, stream means to get the file stream pointer of the current position. After the call is successful, the return value is long type, indicating the offset (in bytes) of the current file pointer relative to the beginning of the file.

  • fread() is used to read binary data from a file and store it in a memory buffer. Its prototype is as follows:
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);

Among them, ptr: the address of the buffer where the data is stored after reading. size: The number of bytes to read elements at a time. count: The number of read elements. stream: file pointer. When the call is successful, the return value is the number of elements actually read, which is usually equal to the count parameter. If an end-of-file character is encountered or an error occurs during the read operation, the return value will be less than count.

  • fwrite() is used to write the binary data in the memory to the file according to the specified number and size. Its prototype is as follows:
size_t fwrite(void *ptr, size_t size, size_t count, FILE *stream);

Among them, ptr: pointer to the data to be written. size: The size (in bytes) of each data block. count: The number of data blocks to write. stream: FILE structure pointer pointing to the target file.

Two, stmt related functions

Using stmt (or called statement) can precompile SQL statements, which can improve code execution efficiency and security. When we use stmt, we can bind the parameter placeholder (such as "?") that needs to be passed in the SQL query with the actual parameter value, and then the database will precompile the SQL statement and generate an execution plan. Afterwards, each time the SQL statement is executed, the plan can be executed by simply filling the actual parameter values ​​into the placeholder positions without recompiling the entire SQL statement. This can greatly reduce the overhead of the database system and improve the response speed of the application.

1. The specific process of writing local (picture) data to the database is as follows

1. Create a MYSQL_STMT *stmt to represent the prepared statement
2. Use the mysql_stmt_init() function to initialize the MYSQL_STMT structure object stmt
3. Use the mysql_stmt_prepare() function to bind the SQL statement to be executed to the object stmt
4. Create a structure MYSQL_BIND *param is used to bind the variable of the parameter in the SQL statement
5. Use the mysql_stmt_bind_param() function to set the parameters required in the SQL statement
6. Use the mysql_stmt_send_long_data() function to bind the binary data to the placeholder of the preprocessed SQL statement
7. Use the mysql_stmt_execute() function to execute the SQL statement
8. Use the mysql_stmt_fetch() function to obtain the data in the result set
9. After use, use the mysql_stmt_close() function to release the MYSQL_STMT object

2. The specific process of reading (picture) data from the database is as follows

1. Create a MYSQL_STMT *stmt to represent the prepared statement
2. Use the mysql_stmt_init() function to initialize the MYSQL_STMT structure object stmt
3. Use the mysql_stmt_prepare() function to bind the SQL statement to be executed to the object stmt
4. Create a structure MYSQL_BIND *result is used to bind the result set of parameters in the SQL statement
5. Use the mysql_stmt_bind_result(stmt,&result) function to bind the query result to the result structure
6. Use the mysql_stmt_execute() function to execute the SQL statement
7. Use the mysql_stmt_store_result() function Save all result rows in the local buffer
8. Use the mysql_stmt_fetch() function to obtain the row data in the result set and store it in result.buffer
9. Use the mysql_stmt_fetch_column() function to obtain the result set column data and store it in the buffer 9. After use
, use the mysql_stmt_close() function to release the MYSQL_STMT object
insert image description here

#include<stdio.h>
#include<string.h>
#include<mysql.h>

#define MING_DB_IP           "192.168.42.128"
#define MING_DB_PORT         3306
#define MING_DB_USENAME      "admin"
#define MING_DB_PASSWORD     "123456"
#define MING_DB_DEFAULTDB    "MING_DB"
#define FILE_IMAGE_LENGTH    (64*1024)


#define SQL_INSERT_IMG_USER     "insert TBL_USER(U_NAME,U_GENDER,U_IMG) values('zxm','women',?);"
#define SQL_SELECT_IMG_USER     "select U_IMG from TBL_USER where U_NAME='zxm';"


//从客户端读取图片存入节点服务器的buffer
    //filename:图片路径; buffer:存储图片
int read_image(char *filename,char *buffer){
    
    
    if (filename == NULL || buffer ==NULL ) return -1;
    FILE *fp=fopen(filename,"rb"); //以二进制模式读取该文件
    if (fp == NULL){
    
    
        printf("fopen failed\n");
        return -2;
    }

    //检测文件大小file
      
    fseek(fp,0,SEEK_END);
    int length=ftell(fp);
    fseek(fp,0,SEEK_SET);

    int size=fread(buffer,1,length,fp);
    if (size != length){
    
    
        printf("fread failed:%d\n",size);
        return -3;
    }

    fclose(fp);
    return size;
}

//从节点服务器的buffer写入图片到客户端
int write_image(char *filename,char *buffer,int length){
    
    
    if (filename == NULL || buffer ==NULL || length <=1) return -1;
    FILE *fp=fopen(filename,"wb+"); 
    if (fp == NULL){
    
    
        printf("fopen failed\n");
        return -2;
    }    

    int size=fwrite(buffer,1,length,fp);
    if (size != length){
    
    
        printf("fwrite failed:%d\n",size);
        return -3;
    }

    fclose(fp);
    return size;
}

//从节点服务器的buffer读取数据到数据库
int mysql_write(MYSQL *handle,char *buffer,int length){
    
    
    if (handle ==NULL || buffer == NULL || length <=0) return -1;

    MYSQL_STMT *stmt=mysql_stmt_init(handle);
    int ret=mysql_stmt_prepare(stmt,SQL_INSERT_IMG_USER,strlen(SQL_INSERT_IMG_USER));
    if (ret){
    
    
        printf("mysql_stmt_prepare:%s\n",mysql_error(handle));
        return -2;
    }

    MYSQL_BIND param={
    
    0};
    param.buffer_type=MYSQL_TYPE_LONG_BLOB;
    param.buffer=NULL;
    param.is_null=0;
    param.length=NULL;

    ret=mysql_stmt_bind_param(stmt,&param);
    if (ret){
    
    
        printf("mysql_stmt_bind_param:%s\n",mysql_error(handle));
        return -3;       
    }

    ret=mysql_stmt_send_long_data(stmt,0,buffer,length);
    if (ret){
    
    
        printf("mysql_stmt_send_long_data:%s\n",mysql_error(handle));
        return -4;       
    }   

    ret=mysql_stmt_execute(stmt);
    if (ret){
    
    
        printf("mysql_stmt_execute:%s\n",mysql_error(handle));
        return -5;       
    }

    ret=mysql_stmt_close(stmt) ;  
    if (ret){
    
    
        printf("mysql_stmt_close:%s\n",mysql_error(handle));
        return -6;       
    }     

    return ret;
}

//从数据库写入数据到节点服务器的buffer
int mysql_read(MYSQL *handle,char *buffer,int length){
    
    
    if (handle ==NULL || buffer == NULL || length <=0) return -1;

    MYSQL_STMT *stmt=mysql_stmt_init(handle);
    int ret=mysql_stmt_prepare(stmt,SQL_SELECT_IMG_USER,strlen(SQL_SELECT_IMG_USER));
    if (ret){
    
    
        printf("mysql_stat_prepare:%s\n",mysql_error(handle));
        return -2;
    }   

    MYSQL_BIND result={
    
    0};
    result.buffer_type=MYSQL_TYPE_LONG_BLOB;
    unsigned long total_length=0;
    result.length=&total_length;

    ret=mysql_stmt_bind_result(stmt,&result);
    if (ret){
    
    
        printf("mysql_stmt_bind_result:%s\n",mysql_error(handle));
        return -3;
    }     

    ret=mysql_stmt_execute(stmt);
    if (ret){
    
    
        printf("mysql_stmt_execute:%s\n",mysql_error(handle));
        return -4;
    }         

    ret=mysql_stmt_store_result(stmt);
    if (ret){
    
    
        printf("mysql_stmt_store_result:%s\n",mysql_error(handle));
        return -5;
    }    

    while (1)
    {
    
    
        //获取下一行数据并存储到 result.buffer 中
        ret=mysql_stmt_fetch(stmt);
        if (ret !=0 && ret != MYSQL_DATA_TRUNCATED ) break;

        int start=0;
        while(start <(int)total_length ){
    
    
            /*buffer 是一个指向缓冲区起始地址的指针,而 start 是一个表示偏移量的整数。
            因此,buffer+start 的结果就是一个指向缓冲区中某个特定位置的指针。
            result.buffer指向的是buffer+start*/
            result.buffer=buffer+start; 
            //存储实际读取到的数据长度,单位为字节 
            result.buffer_length=1;
            /*在使用 mysql_stmt_fetch_column() 函数从结果集中读取数据时,每次只会读取一部分数据并存储到由
             result.buffer所指向的缓冲区中。如果要将多个数据段合并成完整的数据块,
            则需要利用偏移量来调整存储位置。具体地说,可以通过不断修改 start 的值来控制写入数据时所处的位置。*/
            mysql_stmt_fetch_column(stmt,&result,0,start);
            start+=result.buffer_length;
        }
    }

    mysql_stmt_close(stmt);

    return total_length;
      
}


int main(){
    
    

    //定义一个MYSQL类型的结构体变量,并通过调用mysql_init()函数对其进行初始化
    //调用mysql_error()函数来获取有关错误信息
     MYSQL mysql;
    
    if (mysql_init(&mysql)==NULL){
    
    
        printf("mysql_init:%s\n",mysql_error(&mysql));
        return -1;
    }

    //mysql_real_connect()用于连接到MySQL服务器.它需要以下参数:
    /*1、MYSQL类型的结构体指针,该结构体已由mysql_init()初始化。
      2、MySQL服务器所在主机名或IP地址。
      3、登录MySQL服务器时使用的用户名。
      4、登录MySQL服务器时使用的密码。
      5、要连接的数据库名称。
      6、端口号(默认为3306)。
      7、规定 socket    8、规定不同的连接选项
    */
    if(!mysql_real_connect(&mysql,MING_DB_IP,MING_DB_USENAME,MING_DB_PASSWORD,
    MING_DB_DEFAULTDB,MING_DB_PORT,NULL,0)){
    
        //等于0,不成功
        printf("mysql_real_connect:%s\n",mysql_error(&mysql));
        return -2;
    }



    printf("case:mysql read image and write image \n");
    char buffer[FILE_IMAGE_LENGTH]={
    
    0};

    int length=read_image("/home/zxm/share/06mysqlPicture/0voice.jpg",buffer);
    if (length < 0) goto Exit;
    
    mysql_write(&mysql,buffer,length);


    printf("case:mysql read mysql and write image \n");
    memset(buffer,0,FILE_IMAGE_LENGTH);
    length=mysql_read(&mysql,buffer,FILE_IMAGE_LENGTH);

    write_image("a.jpg",buffer,length);


Exit:
    mysql_close(&mysql);
    return 0;

}

Guess you like

Origin blog.csdn.net/Ricardo2/article/details/130832764