• 认真地记录技术中遇到的坑!

杂记:常用的一些小知识

C/C++ Moxun 9个月前 (02-01) 214次浏览 0个评论

1.Base64
A.base64编码的原因
网络传送渠道并不支持所有的字节,例如传统的邮件只支持可见字符的传送,像ASCII码的控制字符就不能通过邮件传送。这样用途就受到了很大的限制,比如图片二进制流的每个字节不可能全部是可见字符,所以就传送不了。最好的方法就是在不改变传统协议的情 况下,做一种扩展方案来支持二进制文件的传送。把不可打印的字符也能用可打印字符来表示,问题就解决了。Base64编码应运而生,Base64就是一种 基于64个可打印字符来表示二进制数据的表示方法。
B.base64编码原理
Base64编码的思想是是采用64个基本的ASCII码字符对数据进行重新编码。它将需要编码的数据拆分成字节数组。以3个字节为一组。按顺序排列24 位数据,再把这24位数据分成4组,即每组6位。再在每组的的最高位前补两个0凑足一个字节。这样就把一个3字节为一组的数据重新编码成了4个字节。当所要编码的数据的字节数不是3的整倍数,也就是说在分组时最后一组不够3个字节。这时在最后一组填充1到2个0字节。

C++实现图片到Base64的编解码:

<span style="font-size:18px;">#include <string>
using namespace std;

class ZBase64
{
public:
    /*编码
    DataByte
        [in]输入的数据长度,以字节为单位
    */
    string Encode(const unsigned char* Data,int DataByte);
    /*解码
    DataByte
        [in]输入的数据长度,以字节为单位
    OutByte
        [out]输出的数据长度,以字节为单位,请不要通过返回值计算
        输出数据的长度
    */
    string Decode(const char* Data,int DataByte,int& OutByte);
};</span>

``````cpp

#include "ZBase64.h"

string ZBase64::Encode(const unsigned char* Data,int DataByte)
{
    //编码表
    const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    //返回值
    string strEncode;
    unsigned char Tmp[4]={0};
    int LineLength=0;
    for(int i=0;i&gt; 2];
        strEncode+= EncodeTable[((Tmp[1] &lt;&gt; 4)) &amp; 0x3F];
        strEncode+= EncodeTable[((Tmp[2] &lt;&gt; 6)) &amp; 0x3F];
        strEncode+= EncodeTable[Tmp[3] &amp; 0x3F];
        if(LineLength+=4,LineLength==76) {strEncode+="\r\n";LineLength=0;}
    }
    //对剩余数据进行编码
    int Mod=DataByte % 3;
    if(Mod==1)
    {
        Tmp[1] = *Data++;
        strEncode+= EncodeTable[(Tmp[1] &amp; 0xFC) &gt;&gt; 2];
        strEncode+= EncodeTable[((Tmp[1] &amp; 0x03) &lt;&gt; 2];
        strEncode+= EncodeTable[((Tmp[1] &amp; 0x03) &lt;&gt; 4)];
        strEncode+= EncodeTable[((Tmp[2] &amp; 0x0F) &lt;&lt; 2)];
        strEncode+= &quot;=&quot;;
    }

    return strEncode;
}

string ZBase64::Decode(const char* Data,int DataByte,int&amp; OutByte)
{
    //解码表
    const char DecodeTable[] =
    {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        62, // '+'
        0, 0, 0,
        63, // '/'
        52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9'
        0, 0, 0, 0, 0, 0, 0,
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
        13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z'
        0, 0, 0, 0, 0, 0,
        26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
        39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z'
    };
    //返回值
    string strDecode;
    int nValue;
    int i= 0;
    while (i &lt; DataByte)
    {
        if (*Data != '\r' &amp;&amp; *Data!='\n')
        {
            nValue = DecodeTable[*Data++] &lt;&lt; 18;
            nValue += DecodeTable[*Data++] &lt;&gt; 16;
            OutByte++;
            if (*Data != '=')
            {
                nValue += DecodeTable[*Data++] &lt;&gt; 8;
                OutByte++;
                if (*Data != '=')
                {
                    nValue += DecodeTable[*Data++];
                    strDecode+=nValue &amp; 0x000000FF;
                    OutByte++;
                }
            }
            i += 4;
        }
        else// 回车换行,跳过
        {
            Data++;
            i++;
        }
     }
    return strDecode;
}

这里提供的解码函数并不好用,以后有时间再研究解决方法。
注:Base64编码后会有换行符的解决方法
据RFC 822规定,每76个字符,还需要加上一个回车换行
有时就因为这些换行弄得出了问题,解决办法如下,替换所有换行和回车,所以不管用什么语言来解码Base64都要先处理换行和回车。
[java] view plain copy
String bTemp = Base64.encodeBase64String(“123”.getBytes());
bTemp = bTemp.replaceAll(“[\s*\t\n\r]”, “”);

    验证自己的Base64编码是否正确,可以使用在线工具:http://www.vgot.net/test/image2base64.php?

2.网络字节序和主机字节序
实际上就是大端存储和小端存储的问题,intel处理器是使用小端存储的,但是在网络中传输时是使用的大端存储,JAVA虚拟机默认为大端存储,C++默认为小端存储,所以使用C++和JAVA通信时要注意字节序的转换问题。,Socket通信问题可以使用工具NetAssist.exe进行简单的测试。

3.C++使用Http的GET和Post方式
A.GET是把参数都带在URL里的,这种模式下,参数的长度是有限制的,当参数过大时会导致无法接收数据或者发送失败。(如果POST也把参数带在URL里,那么会有同样的问题)
B.不管是GET还是POST,只要是把参数带在URL中,那么只能有一个HTTP头,否则会导致无法接收数据。
C.如果需要通过HTTP的方式,传递大文件,那么需要把这个大文件放在POST的数据包里,在这种方式下数据包的大小是没有限制的。
D.测试工具可以使用Postman进行简单测试。

4.C++中char是否带有符号是取决于机器的,它可能是有符号的也可能是无符号的,对于某些特殊应用,硬件设备为了节约硬件资源可能会使用unsigned char 来传输数据,此时可以用int接收,而不能使用char,因为有可能发生溢出。


转载请注明出处 杂记:常用的一些小知识
喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址