由于项目用到了字节数组与文本互相转换,所以自己写了一对方法用来把字节数组转成可见字符串,及把字符串转成字节数组的BASE64算法。
使用toBase64String的时候默认的是加上了回车换行的处理,但是在fromBase64String的时候无论有没有回车换行符都可以正确的转换。
这里的算法完全是自己由Base64思想自己完出来的,如果错误敬请指正。
使用的示例:
BYTE* bts(NULL);
int len;
LPCTSTR str=_T("abcdefg123456");
bts=this->fromBase64String(str, len);//转成字节数组
CString t = this->toBase64String(bts, len);//由字节数组再转回字符串
delete bts;
实现代码:
CString CTAXGDlg::toBase64String(BYTE* btyArray, int length)
{
CString strResult;
if (length==0)
{
return strResult;
}
TCHAR base64[65]={
_T('A'), _T('B'), _T('C'), _T('D'), _T('E'), _T('F'), _T('G'), _T('H'), _T('I'), _T('J'), _T('K'), _T('L'), _T('M'), _T('N'), _T('O'), _T('P'),
_T('Q'), _T('R'), _T('S'), _T('T'), _T('U'), _T('V'), _T('W'), _T('X'), _T('Y'), _T('Z'), _T('a'), _T('b'), _T('c'), _T('d'), _T('e'), _T('f'),
_T('g'), _T('h'), _T('i'), _T('j'), _T('k'), _T('l'), _T('m'), _T('n'), _T('o'), _T('p'), _T('q'), _T('r'), _T('s'), _T('t'), _T('u'), _T('v'),
_T('w'), _T('x'), _T('y'), _T('z'), _T('0'), _T('1'), _T('2'), _T('3'), _T('4'), _T('5'), _T('6'), _T('7'), _T('8'), _T('9'), _T('+'), _T('/'),
_T('=')
};
int nRemainder = length % 3;//num为剩余的字节数
int nlength = (length / 3) * 4;
if (nRemainder!=0)
{
nlength += 4;
}
int lines = nlength / 0x50;
if ((nlength % 0x50) == 0)
{
lines--;
}
nlength+=lines * 2;//×2是因为有两个回车换行符
TCHAR* chrArray=new TCHAR[nlength];
::ZeroMemory(chrArray, nlength*sizeof(TCHAR));
int charIndex(0);
int nLineChars(0);
int nSourceIndex(0);
for (nSourceIndex = 0; nSourceIndex < length - nRemainder; nSourceIndex += 3)
{
//每三个字节转成四个字节且,这四个字节值都不大于64,这就保证了只会出现64个字符中的一个。
chrArray[charIndex++] = base64[(btyArray[nSourceIndex] & 0xfc) >> 2];
chrArray[charIndex++] = base64[((btyArray[nSourceIndex] & 0x3) << 4) | ((btyArray[nSourceIndex + 1] & 0xF0) >> 4)];
chrArray[charIndex++] = base64[((btyArray[nSourceIndex + 1] & 0xF) << 2) | ((btyArray[nSourceIndex + 2] & 0xc0) >> 6)];
chrArray[charIndex++] = base64[btyArray[nSourceIndex + 2] & 0x3f];
nLineChars += 4;
if (nLineChars == 0x50)
{
chrArray[charIndex++] = _T('/r');
chrArray[charIndex++] = _T('/n');
nLineChars = 0;
}
}
//处理剩余的字节,如果剩余字节数不为0且没有添加换行符则添加换行符。
if (((nRemainder != 0)) && (nLineChars == 0x50))
{
chrArray[charIndex++] = _T('/r');
chrArray[charIndex++] = _T('/n');
}
switch (nRemainder)
{
case 1:
chrArray[charIndex++] = base64[(btyArray[nSourceIndex] & 0xfc) >> 2];
chrArray[charIndex++] = base64[(btyArray[nSourceIndex] & 0x3) << 4];
chrArray[charIndex++] = base64[0x40];
chrArray[charIndex++] = base64[0x40];
break;
case 2:
chrArray[charIndex++] = base64[(btyArray[nSourceIndex] & 0xfc) >> 2];
chrArray[charIndex++] = base64[((btyArray[nSourceIndex] & 3) << 4) | ((btyArray[nSourceIndex + 1] & 240) >> 4)];
chrArray[charIndex++] = base64[(btyArray[nSourceIndex + 1] & 15) << 2];
chrArray[charIndex++] = base64[0x40];
break;
}
strResult=CString(chrArray, charIndex);
delete[] chrArray;
return strResult;
}
BYTE* CTAXGDlg::fromBase64String(LPCTSTR text, int& length)
{
//去掉回车换行符
int textLength(0);
const TCHAR* pText=text;
while(*pText++)
{
textLength++;
}
TCHAR* chrArray=new TCHAR[textLength+1];
ZeroMemory(chrArray, sizeof(TCHAR)*(textLength+1));
int nCount=0;
for(int charIndex=0;charIndex<textLength;charIndex++)
{
TCHAR tmpChar=text[charIndex];
if (tmpChar==_T('/r') || tmpChar==_T('/n'))
{
continue;
}
if (tmpChar==_T('='))
{
break;
}
chrArray[nCount++]=tmpChar;
}
int nRemainder=nCount%4;
int tmpLength = (nCount/4) * 3;
if(nRemainder!=0)
{
tmpLength+=3;
}
BYTE* btyArray=new BYTE[tmpLength];
int byteIndex(0);
int nSourceIndex(0);
for (nSourceIndex = 0; nSourceIndex < nCount-nRemainder; nSourceIndex++)
{
//每四个字符转成三个字节,这四个字符值都不大于64。
TCHAR c1=chrArray[nSourceIndex++];
TCHAR c2=chrArray[nSourceIndex++];
TCHAR c3=chrArray[nSourceIndex++];
TCHAR c4=chrArray[nSourceIndex];
BYTE b1=getBase64Byte(c1);
BYTE b2=getBase64Byte(c2);
BYTE b3=getBase64Byte(c3);
BYTE b4=getBase64Byte(c4);
btyArray[byteIndex++] = (BYTE)(((b1 & 0x3f) << 2)|((b2 & 0xf0) >> 4));
btyArray[byteIndex++] = (BYTE)(((b2 & 0xf) << 4)|((b3 & 0xfc) >> 2));
btyArray[byteIndex++] = (BYTE)(((b3 & 0x3) << 6)|(b4 & 0x3f));
}
switch(nRemainder)
{
case 3:
{
TCHAR c1=chrArray[nSourceIndex++];
TCHAR c2=chrArray[nSourceIndex++];
TCHAR c3=chrArray[nSourceIndex];
BYTE b1=getBase64Byte(c1);
BYTE b2=getBase64Byte(c2);
BYTE b3=getBase64Byte(c3);
BYTE v1=(BYTE)(((b1 & 0x3f) << 2)|((b2 & 0xf0) >> 4));
BYTE v2=(BYTE)(((b2 & 0xf) << 4)|((b3 & 0xfc) >> 2));
btyArray[byteIndex++] = v1;
btyArray[byteIndex++] = v2;
}
break;
case 2:
{
TCHAR c1=chrArray[nSourceIndex++];
TCHAR c2=chrArray[nSourceIndex];
BYTE b1=getBase64Byte(c1);
BYTE b2=getBase64Byte(c2);
BYTE v1=(BYTE)(((b1 & 0x3f) << 2)|((b2 & 0xf0) >> 4));
btyArray[byteIndex++] = v1;
}
break;
}
delete[] chrArray;
length=byteIndex;
return btyArray;
}
BYTE CTAXGDlg::getBase64Byte(TCHAR value)
{
BYTE b(64);
if (value>=_T('A') && value<=_T('Z'))
{
b=(BYTE)(value-_T('A'));
}
else if (value>=_T('a') && value<=_T('z'))
{
b=(BYTE)(value-_T('a')+26);
}
else if (value>=_T('0') && value<=_T('9'))
{
b=(BYTE)(value-_T('0')+52);
}
else if (value==_T('+')||value==_T('*')||value==_T('['))
{
b=(BYTE)62;
}
else if (value==_T('/')||value==_T('-')||value==_T(']'))
{
b=(BYTE)63;
}
return b;
}