美文网首页
通过二维码传输少量文本

通过二维码传输少量文本

作者: laxe | 来源:发表于2017-06-08 18:11 被阅读0次

    有时候想通过图片传递一些信息,比如公司电脑上一些自己的文档,拍照的话还得自己重新整理出来,要是能将文档转成二维码,用手机扫出来,多方便,本文对此进行一些尝试。

    二维码能传输的信息量是很少的,直接将文档内容转成二维码很不现实,先对文档进行压缩再传输比较可行,先用WinRAR对原文件进行压缩。
    然后需要将rar转换成可打印字符,一个汉字的二维码比两个ascii字符的二维码复杂,这里考虑将rar转成可打印的ascii字符。标准ascii里有95个可打印字符,那就选64个,可表示6个比特位。

    rar文件 可打印字符
    6个比特位 一个字符
    24个比特位/3个字节 4个字符

    所以,rar文件的字节数和可打印字符的字节数之比是3:4。

    将rar文件转换为可打印字符的代码:

    // encode.c
    //input: src.rar output: dest.txt
    #include <stdio.h>
    #include <string.h>
    
    unsigned char table[]=
    {
        '0','1','2','3','4','5','6','7','8','9','<','>',
        'A','B','C','D','E','F','G','H','I','J','K','L','M',
        'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
        'a','b','c','d','e','f','g','h','i','j','k','l','m',
        'n','o','p','q','r','s','t','u','v','w','x','y','z'
    };
    
    // 当到达文件尾不足3个字符时, 末尾补0, 最多会有2个空字符, 对rar文件无影响
    int read3chars(FILE *fin, unsigned char *re)
    {
        int t;
        unsigned char buf[3];
        memset(buf, 0, 3*sizeof(unsigned char));
    
        t = fgetc(fin);
        if(t == EOF) return 1;
        buf[0] = t;
        t = fgetc(fin);
        if(t == EOF) goto last;
        buf[1] = t;
        t = fgetc(fin);
        if(t == EOF) goto last;
        buf[2] = t;
    
    last:
        unsigned char a = (buf[0]&0xFC)>>2;
        unsigned char b = (buf[0]&0x03)<<4 | (buf[1]&0xF0)>>4;
        unsigned char c = (buf[1]&0x0F)<<2 | buf[2]>>6;
        unsigned char d = buf[2]&0x3F;
        re[0] = table[a];
        re[1] = table[b];
        re[2] = table[c];
        re[3] = table[d];
    
        return 0;
    }
    
    int main()
    {
        FILE *fin = fopen("src.rar", "rb");
        if(fin == NULL)
        {
            puts("cann't open src.rar!");
            getchar();
            return -1;
        }
        FILE *fout = fopen("dest.txt", "w");
        for(;;)
        {
            unsigned char buf[4];
            int ret = read3chars(fin, buf);
            if(ret == 1) break;
            fputc(buf[0], fout);
            fputc(buf[1], fout);
            fputc(buf[2], fout);
            fputc(buf[3], fout);
        }
        fclose(fin);
        fclose(fout);
        return 0;
    }
    

    将生成的字符分批次通过二维码扫描工具传输。
    也可以直接改上面的main函数:

    int main()
    {
        FILE *fin = fopen("src.rar", "rb");
        if(fin == NULL)
        {
            puts("cann't open src.rar!");
            getchar();
            return -1;
        }
        char dest[] = "A.txt";
        FILE *fout = fopen(dest, "w");
        for(int i=1;;++i)
        {
            unsigned char buf[4];
            int ret = read3chars(fin, buf);
            if(ret == 1) break;
            fputc(buf[0], fout);
            fputc(buf[1], fout);
            fputc(buf[2], fout);
            fputc(buf[3], fout);
            if(i == 256)
            {
                i = 0;
                fclose(fout);
                ++dest[0];
                fout = fopen(dest, "w");
            }
        }
        fclose(fin);
        fclose(fout);
        return 0;
    }
    

    将扫码得到的字符组合在一起,放到txt文件里,然后执行以下的程序。这里并没有对BOM字符进行处理,仅仅是和上面的程序一起进行测试。

    // decode.cpp
    // input: dest.txt output: dest.rar
    #include <cstdio>
    #include <hash_map>
    
    char table[]=
    {
        '0','1','2','3','4','5','6','7','8','9','<','>',
        'A','B','C','D','E','F','G','H','I','J','K','L','M',
        'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
        'a','b','c','d','e','f','g','h','i','j','k','l','m',
        'n','o','p','q','r','s','t','u','v','w','x','y','z'
    };
    __gnu_cxx::hash_map<unsigned char, unsigned char> retable;
    
    // 一定是4字节的整数倍
    int read4chars(FILE *fin, unsigned char *ret)
    {
        unsigned char buf[4];
        int t = fgetc(fin);
        if(t == EOF) return -1;
        buf[0] = t;
        buf[1] = fgetc(fin);
        buf[2] = fgetc(fin);
        buf[3] = fgetc(fin);
    
        unsigned char a = retable[buf[0]];
        unsigned char b = retable[buf[1]];
        unsigned char c = retable[buf[2]];
        unsigned char d = retable[buf[3]];
        ret[0] = a<<2 | b>>4;
        ret[1] = b<<4 | c>>2;
        ret[2] = c<<6 | d;
    
        return 0;
    }
    
    int main()
    {
        for(unsigned char i=0; i<64; ++i)
            retable.insert(std::make_pair(table[i], i));
    
        FILE *fin = fopen("dest.txt", "r");
        if(fin == NULL)
        {
            puts("cann't open dest.txt!");
            getchar();
            return -1;
        }
        FILE *fout = fopen("dest.rar", "wb");
        for(;;)
        {
            unsigned char buf[3];
            int res = read4chars(fin, buf);
            if(res == -1) break;
            fputc(buf[0], fout);
            fputc(buf[1], fout);
            fputc(buf[2], fout);
        }
    
        fclose(fin);
        fclose(fout);
        return 0;
    }
    

    这和Base64编码的原理是一样的。

    相关文章

      网友评论

          本文标题:通过二维码传输少量文本

          本文链接:https://www.haomeiwen.com/subject/pcytqxtx.html