算法系列8《Base64》
? ? ? ? Base64是網(wǎng)絡(luò)上最常見的用于傳輸8Bit字節(jié)代碼的編碼方式之一,Base64編碼可用于在HTTP環(huán)境下傳遞較長的標(biāo)識信息。在其他應(yīng)用程序中,也常常需要把二進(jìn)制數(shù)據(jù)編碼為適合放在URL(包括隱藏表單域)中的形式。此時,采用Base64編碼具有不可讀性,即所編碼的數(shù)據(jù)不會被人用肉眼所直接看到。金融數(shù)據(jù)也常以base64編碼格式提供。
? ? ? ? ?Base64是一種基于64個可打印字符來表示二進(jìn)制數(shù)據(jù)的表示方法。由于2的6次方等于64,所以每6個比特為一個單元,對應(yīng)某個可打印字符。三個字節(jié)有24個比特,對應(yīng)于4個Base64單元,即3個字節(jié)需要用4個可打印字符來表示。它可用來作為電子郵件的傳輸編碼。在Base64中的可打印字符包括字母A-Z、a-z、數(shù)字0-9,這樣共有62個字符,此外兩個可打印符號在不同的系統(tǒng)中而不同。一些如uuencode的其他編碼方法,和之后binhex的版本使用不同的64字符集來代表6個二進(jìn)制數(shù)字,但是它們不叫Base64。
Base64索引表
C++實(shí)現(xiàn)代碼
1. 《Base64.h》
// Base64.h #pragma once #include <windows.h>class CBase64 {// Internal bucket class.class TempBucket{public:BYTE nData[4];BYTE nSize;void Clear() { ::ZeroMemory(nData, 4); nSize = 0; };};PBYTE m_pDBuffer;PBYTE m_pEBuffer;DWORD m_nDBufLen;DWORD m_nEBufLen;DWORD m_nDDataLen;DWORD m_nEDataLen;public:CBase64();virtual ~CBase64();public:virtual PBYTE Encode(const PBYTE, DWORD);virtual PBYTE Decode(const PBYTE, DWORD);virtual CString Encode(LPCSTR sMessage);virtual CString Decode(LPCSTR sMessage);virtual LPCSTR DecodedMessage() const;virtual LPCSTR EncodedMessage() const;virtual void AlloCEncodeDlg(DWORD);virtual void AllocDecode(DWORD);virtual void SetEncodeBuffer(const PBYTE pBuffer, DWORD nBufLen);virtual void SetDecodeBuffer(const PBYTE pBuffer, DWORD nBufLen);protected:virtual void _EncodeToBuffer(const TempBucket &Decode, PBYTE pBuffer);virtual ULONG _DecodeToBuffer(const TempBucket &Decode, PBYTE pBuffer);virtual void _EncodeRaw(TempBucket &, const TempBucket &);virtual void _DecodeRaw(TempBucket &, const TempBucket &);virtual BOOL _IsBadMimeChar(BYTE);static char m_DecodeTable[256];static BOOL m_Init;void _Init(); };
2. 《CBase64.cpp》
// CBase64.cpp // CBase64.cpp: implementation of the CBase64 class.// #include "stdAfx.h" #include "Base64.h" #include "DataX.h"using namespace DataX;// Digits... static char Base64Digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";BOOL CBase64::m_Init = FALSE; char CBase64::m_DecodeTable[256];#ifndef PAGESIZE #define PAGESIZE 4096 #endif#ifndef ROUNDTOPAGE #define ROUNDTOPAGE(a) ((((a) / 4096) + 1) * 4096) #endif// // Construction/Destruction //CBase64::CBase64(): m_pDBuffer(NULL),m_pEBuffer(NULL),m_nDBufLen(0),m_nEBufLen(0) {}CBase64::~CBase64() {if (m_pDBuffer != NULL){delete [] m_pDBuffer;}if (m_pEBuffer != NULL){delete [] m_pEBuffer;} }LPCSTR CBase64::DecodedMessage() const {return (LPCSTR) m_pDBuffer; }LPCSTR CBase64::EncodedMessage() const {return (LPCSTR) m_pEBuffer; }void CBase64::AlloCEncodeDlg(DWORD nSize) {if (m_nEBufLen < nSize){if (m_pEBuffer != NULL)delete [] m_pEBuffer;m_nEBufLen = ROUNDTOPAGE(nSize);m_pEBuffer = new BYTE[m_nEBufLen];}::ZeroMemory(m_pEBuffer, m_nEBufLen);m_nEDataLen = 0; }void CBase64::AllocDecode(DWORD nSize) {if (m_nDBufLen < nSize){if (m_pDBuffer != NULL){delete [] m_pDBuffer;}m_nDBufLen = ROUNDTOPAGE(nSize);m_pDBuffer = new BYTE[m_nDBufLen];}::ZeroMemory(m_pDBuffer, m_nDBufLen);m_nDDataLen = 0; }void CBase64::SetEncodeBuffer(const PBYTE pBuffer, DWORD nBufLen) {DWORD ii = 0;AlloCEncodeDlg(nBufLen);while(ii < nBufLen){if (!_IsBadMimeChar(pBuffer[ii])){m_pEBuffer[m_nEDataLen] = pBuffer[ii];m_nEDataLen ++ ;}ii ++ ;} }void CBase64::SetDecodeBuffer(const PBYTE pBuffer, DWORD nBufLen) {AllocDecode(nBufLen);::CopyMemory(m_pDBuffer, pBuffer, nBufLen);m_nDDataLen = nBufLen; }PBYTE CBase64::Encode(const PBYTE pBuffer, DWORD nBufLen) {SetDecodeBuffer(pBuffer, nBufLen);AlloCEncodeDlg(nBufLen * 2);TempBucket Raw;DWORD nIndex = 0;while((nIndex + 3) <= nBufLen){Raw.Clear();::CopyMemory(&Raw, m_pDBuffer + nIndex, 3);Raw.nSize = 3;_EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen);nIndex += 3;m_nEDataLen += 4;}if (nBufLen > nIndex){Raw.Clear();Raw.nSize = (BYTE) (nBufLen - nIndex);::CopyMemory(&Raw, m_pDBuffer + nIndex, nBufLen - nIndex);_EncodeToBuffer(Raw, m_pEBuffer + m_nEDataLen);m_nEDataLen += 4;}return m_pEBuffer; }CString CBase64::Encode(LPCSTR szMessage) {CString strHex = _T("");if (szMessage != NULL){CBase64::Encode((const PBYTE)szMessage, lstrlenA(szMessage));if (m_nEDataLen > 0){AscToHex(m_pEBuffer, m_nEDataLen, strHex);}}return strHex; }PBYTE CBase64::Decode(const PBYTE pBuffer, DWORD dwBufLen) {if (!CBase64::m_Init)_Init();SetEncodeBuffer(pBuffer, dwBufLen);AllocDecode(dwBufLen);TempBucket Raw;DWORD nIndex = 0;while((nIndex + 4) <= m_nEDataLen){Raw.Clear();Raw.nData[0] = CBase64::m_DecodeTable[m_pEBuffer[nIndex]];Raw.nData[1] = CBase64::m_DecodeTable[m_pEBuffer[nIndex + 1]];Raw.nData[2] = CBase64::m_DecodeTable[m_pEBuffer[nIndex + 2]];Raw.nData[3] = CBase64::m_DecodeTable[m_pEBuffer[nIndex + 3]];if (Raw.nData[2] == 255)Raw.nData[2] = 0;if (Raw.nData[3] == 255)Raw.nData[3] = 0;Raw.nSize = 4;_DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen);nIndex += 4;m_nDDataLen += 3;}// If nIndex < m_nEDataLen, then we got a decode message without padding.// We may want to throw some kind of warning here, but we are still required// to handle the decoding as if it was properly padded.if (nIndex < m_nEDataLen){Raw.Clear();for(DWORD ii = nIndex; ii < m_nEDataLen; ii ++ ){Raw.nData[ii - nIndex] = CBase64::m_DecodeTable[m_pEBuffer[ii]];Raw.nSize ++ ;if (Raw.nData[ii - nIndex] == 255)Raw.nData[ii - nIndex] = 0;}_DecodeToBuffer(Raw, m_pDBuffer + m_nDDataLen);m_nDDataLen += (m_nEDataLen - nIndex);}return m_pDBuffer; }CString CBase64::Decode(LPCSTR pszMessage) {if (!pszMessage){return _T("");}CBase64::Decode((const PBYTE)pszMessage, lstrlenA(pszMessage));CString strHex = _T("");if (m_nDDataLen > 0){AscToHex(m_pDBuffer, m_nDDataLen, strHex);}return strHex;}DWORD CBase64::_DecodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) {TempBucket Data;DWORD nCount = 0;_DecodeRaw(Data, Decode);for(int ii = 0; ii < 3; ii ++ ){pBuffer[ii] = Data.nData[ii];if (pBuffer[ii] != 255)nCount ++ ;}return nCount; }void CBase64::_EncodeToBuffer(const TempBucket &Decode, PBYTE pBuffer) {TempBucket Data;_EncodeRaw(Data, Decode);for(int ii = 0; ii < 4; ii ++ )pBuffer[ii] = Base64Digits[Data.nData[ii]];switch(Decode.nSize){case 1:pBuffer[2] = '=';case 2:pBuffer[3] = '=';} }void CBase64::_DecodeRaw(TempBucket &Data, const TempBucket &Decode) {BYTE nTemp;Data.nData[0] = Decode.nData[0];Data.nData[0] <<= 2;nTemp = Decode.nData[1];nTemp >>= 4;nTemp &= 0x03;Data.nData[0] |= nTemp;Data.nData[1] = Decode.nData[1];Data.nData[1] <<= 4;nTemp = Decode.nData[2];nTemp >>= 2;nTemp &= 0x0F;Data.nData[1] |= nTemp;Data.nData[2] = Decode.nData[2];Data.nData[2] <<= 6;nTemp = Decode.nData[3];nTemp &= 0x3F;Data.nData[2] |= nTemp; }void CBase64::_EncodeRaw(TempBucket &Data, const TempBucket &Decode) {BYTE nTemp;Data.nData[0] = Decode.nData[0];Data.nData[0] >>= 2;Data.nData[1] = Decode.nData[0];Data.nData[1] <<= 4;nTemp = Decode.nData[1];nTemp >>= 4;Data.nData[1] |= nTemp;Data.nData[1] &= 0x3F;Data.nData[2] = Decode.nData[1];Data.nData[2] <<= 2;nTemp = Decode.nData[2];nTemp >>= 6;Data.nData[2] |= nTemp;Data.nData[2] &= 0x3F;Data.nData[3] = Decode.nData[2];Data.nData[3] &= 0x3F; }BOOL CBase64::_IsBadMimeChar(BYTE nData) {switch(nData){case '\r': case '\n': case '\t': case ' ' :case '\b': case '\a': case '\f': case '\v':return TRUE;default:return FALSE;} }void CBase64::_Init() { // Initialize Decoding table.int ii;for(ii = 0; ii < 256; ii ++ )CBase64::m_DecodeTable[ii] = -2;for(ii = 0; ii < 64; ii ++ ){CBase64::m_DecodeTable[Base64Digits[ii]] = (CHAR)ii;CBase64::m_DecodeTable[Base64Digits[ii]|0x80] = (CHAR)ii;}CBase64::m_DecodeTable['='] = -1;CBase64::m_DecodeTable['='|0x80] = -1;CBase64::m_Init = TRUE; }
文/yanxin8原創(chuàng),獲取更多信息請訪問http://yanxin8.com/277.html
轉(zhuǎn)載于:https://www.cnblogs.com/iplus/p/4467105.html
總結(jié)
以上是生活随笔為你收集整理的算法系列8《Base64》的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《Code Complete》ch.15
- 下一篇: json数据 提示框flash.