• 将图片(二进制文件)存储于数据库,论文件字节流与二进制字符串相互转换


    开发中遇到存储图片文件于数据库这样的需求。

    我们知道文件本身就是一份二进制数据,不同类型的文件只是编码形式不同,对应的解读形式不同,无论txt文件、jpg文件亦或是mp4文件,本质上都是0和1组成的。而在C++中我们可以通过字节流来读写文件,也就是说我们可以把文件读入char数组中,也可以将char数组中的数据写入为文件。

    开发中需要将图片存在数据库中,每个文件几KB,想将之存在数据库表的varchar类型中。大小不是问题,大的话就以text类型存储。关键是,C++读取的文件字节流的char数组是不能直接存储的,因为里面会含有很多‘’。如果按照字符串来理解,就是结束符了。那样一来存的内容就不完整了。

    所以需要将文件字节流的char数组 转化为二进制字符串,再存储数据库。

    从数据库读取后,再转化回文件字节流的char数组。

    每一个char,其实就是一个字节,也就是8bit,每个bit是0或者1。我要做的就是读取每一位,将之转化为字符的'0'或者'1',再存储。

    所以如果原本是N字节的文件,转化后大小为N*8。

    下面是我文件字节流与二进制字符串相互转换的测试程序,参考了几篇文章,里面的程序我略有修改:

    http://blog.csdn.net/k346k346/article/details/52170623

    http://blog.csdn.net/pointer_y/article/details/51525679

    将一个名为timg.jpg的文件,放在程序目录下,程序会将之读取,转化为二进制字符串,然后再转化回去,写入为文件timg2.jpg。

    运行结束后会生成一个timg2.jpg,且和timg.jpg一模一样。

    该程序还会作 字符串转化的测试,效果为:

    #include "stdafx.h"
    #include "iostream"
    #include "string.h"
    #include <fstream>
    #include <assert.h>
    
    using namespace std;
    
    #define P1LEN 10013
    #define P2LEN 80104
    
    /**
     *    设置一个字符第n位bit值
     *    2018-02-06
     */
    int bit_set(unsigned char *p_data, unsigned char position, int flag)   {  
        int i = 0;  
        assert(p_data);  
        if (position > 8 || position < 1 || (flag != 0 && flag != 1))    
            return -1;  
        if (flag != (*p_data >> (position - 1) & 1))  
            *p_data ^= 1 << (position - 1);   
        return 0;
    } 
    
    /**
     *     字符数组 与 二进制字符串 相互转化
     *     2018-02-06
     */
    int char_array_2_binary_str(char ch_buf[],int ch_len,char binary_char_buf[],int binary_char_len,int type){
        if(type!=0&&type!=1)
            return -1;
        //字节流转二进制字符流
        if(type==0){
            if(binary_char_len < 8*ch_len)
                return -1;
            int char_buf_index=0;
            for(int i=0;i<ch_len;++i){
                for(int j=7;j>=0;--j){
                    if(ch_buf[i]>>j&0x1)
                        binary_char_buf[char_buf_index++]='1';
                    else
                        binary_char_buf[char_buf_index++]='0';
                }
            }
            return 0;
        }
        if (type == 1) {
            if(8*ch_len < binary_char_len)
                return -1;
            char tmp_str[9]="";
            int ret_buf_index=0;
            for(int i=0;i<binary_char_len;i=i+8){
                strncpy(tmp_str, binary_char_buf+i, 8);
                for(int j=0; j<8; ++j){ 
                    if (tmp_str[j] == '0')
                        bit_set((unsigned char *)ch_buf+ret_buf_index, 8-j, 0);
                    if (tmp_str[j] == '1')
                        bit_set((unsigned char *)ch_buf+ret_buf_index, 8-j, 1);
                }
                ret_buf_index++;
            }
            return 0;
        }
    }
    
    
    int _tmain(int argc, _TCHAR* argv[]) {
        ////////首先,字符串转换测试////////////////
        char* txt = "异度神剑";
        cout << "原始字符串为:"<< txt << endl << endl;
        char binary_txt_buf[65];
        char_array_2_binary_str(txt,8,binary_txt_buf,64,0);
        binary_txt_buf[64] = '';
        cout << "转化后的二进制字符串为:" << binary_txt_buf << endl << endl;
        char txt2[9];
        char_array_2_binary_str(txt2,8,binary_txt_buf,64,1);
        txt2[8] = '';
        cout << "转化回原始字符串为:" <<txt2 << endl << endl;
        ///////字符串转换测试结束/////////////////
    
        ///////文件转换测试///////////////////////
        const char * filename = "timg.jpg";  
        const char * filename2 = "timg2.jpg"; 
        ifstream infile(filename,ios::in|ios::binary);
        if(!infile) 
            abort( );
        // 存储图片的char数组空间
        char pic_buf[P1LEN];
        infile.read(pic_buf,P1LEN);
        infile.close();
        // 转换成2进制字符串的存储空间
        char ret_buf[P2LEN];
        char_array_2_binary_str(pic_buf,P1LEN,ret_buf,P2LEN,0);
    
        // 转换回来
        char pic_buf2[P1LEN];
        char_array_2_binary_str(pic_buf2,P1LEN,ret_buf,P2LEN,1);
        ofstream outfile(filename2,ios::out|ios::binary);
        if(!outfile) 
            abort( );
        // 写入文件,生成timg2.jpg
        outfile.write(pic_buf2,P1LEN);
        outfile.close();
        ///////文件转换测试结束///////////////////////    
        return 0;
    }

     本来需求就是存储图片于数据库,理论上已经实现了。现在我想到字符串和二进制的转化应该是很有趣的。比如以后我写文章:1101001011101100101101101100100011001001111100011011110110100011

    你能看懂什么意思吗?

    但我用自己程序转化一下,就看懂了。

    以后可以写个带界面的字符串和二进制的转化程序。

    就可以很方便地对自己写的日记作加密了。

    到时我会将代码上传到github,或可期待开个新坑……

  • 相关阅读:
    字符串翻转
    windows套接字相关函数
    Windows多线程同步系列之一-----互斥对象
    Dos命令---ipconfig
    windows多线程没那么难
    CreateThread简单那多线程编程
    TCP/IP协议详解概述
    正则表达式小试牛刀--匹配我的csdn博文标题
    wireshark----教你如何抓包
    HDU1385 (Floyd记录路径)
  • 原文地址:https://www.cnblogs.com/rixiang/p/8421486.html
Copyright © 2020-2023  润新知