zoukankan      html  css  js  c++  java
  • 算法系列8《Base64》

            Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,Base64编码可用于在HTTP环境下传递较长的标识信息。在其他应用程序中,也常常需要把二进制数据编码为适合放在URL(包括隐藏表单域)中的形式。此时,采用Base64编码具有不可读性,即所编码的数据不会被人用肉眼所直接看到。金融数据也常以base64编码格式提供。



             Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于2的6次方等于64,所以每6个比特为一个单元,对应某个可打印字符。三个字节有24个比特,对应于4个Base64单元,即3个字节需要用4个可打印字符来表示。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后binhex的版本使用不同的64字符集来代表6个二进制数字,但是它们不叫Base64。


    Base64索引表





    C++实现代码





    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 '
    ': case '
    ': case '	': case ' ' :
    	case '': 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原创,获取更多信息请访问http://yanxin8.com/277.html


  • 相关阅读:
    面试题27:二叉树的镜像
    面试题26:树的子结构
    面试题25:合并两个排序的链表
    面试题24:反转链表
    面试题23:链表中环的入口节点
    面试题22:链表中倒数第k个节点
    欧拉函数的使用
    C++ STL 全排列函数详解
    Ubuntu系统安装网易云音乐、搜狗输入法
    Ubuntu系统 安装谷歌 Chrome 浏览器
  • 原文地址:https://www.cnblogs.com/iplus/p/4467105.html
Copyright © 2011-2022 走看看