在我創業的一個項目中,為了節約網絡帶寬,因此在網絡中傳輸數據需要實現緊湊存取,在國防,科研,航天,軍工等多個領域其實也有類似的需求。
實現緊湊存取,不是按一個字節一個字節地存取,而是按位存取。比如一個字節,我們可以存儲8個bool信息,廢話少說,直接分享代碼備注:裡面的代碼算法值得優化)。
//以下為函數定義
- /***********************************************************************/
- /* 函數作用:從buffer讀一個位 */
- /* 參數pBuffer[in]:指定buffer */
- /* 參數nStart[in]:指定位置 */
- /* 參數nEnd[out]:返回結束位置 */
- /* 參數retByte[out]:返回讀取結果值 */
- /* 返回:void */
- /***********************************************************************/
- void ReadOneBit( byte* pBuffer, int nStart, /* out */int& nEnd, /* out */ byte& retByte );
- /***********************************************************************/
- /* 函數作用:從指定buffer裡讀任意一段位置數據 */
- /* 參數pBuffer[in]:指定buffer */
- /* 參數nStart[in]:指定位置 */
- /* 參數btLength[in]:讀取長度 */
- /* 參數nEnd[out]:返回結束位置 */
- /* 參數retData[out]:返回讀取結果值,支持任意數據類型 */
- /* 返回:void */
- /***********************************************************************/
- template<typename T>
- void ReadDataFromBuffer( byte* pBuffer, int nStart, byte btLength, /* out */int& nEnd, /* out */ T& retData );
- /***********************************************************************/
- /* 函數作用:從指定buffer裡讀取一段字符串 */
- /* 參數pBuffer[in]:指定buffer */
- /* 參數nStart[in]:指定位置 */
- /* 參數nCount[in]:字符串長度 */
- /* 參數nEnd[out]:返回結束位置 */
- /* 參數pRetData[out]:返回讀取字符串結果 */
- /* 返回:void */
- /***********************************************************************/
- void ReadStringFromBuffer( byte* pBuffer, int nStart, int nCount, /* out */int& nEnd, /* out */char* pRetData );
- /***********************************************************************/
- /* 函數作用:向buffer寫一個位 */
- /* 參數pBuffer[in]:指定buffer */
- /* 參數btData[in]:需要寫入的值 */
- /* 參數nStart[in]:指定位置 */
- /* 參數nEnd[out]:返回結束位置 */
- /* 返回:void */
- /***********************************************************************/
- void WriteOneBit( byte* pBuffer, byte btData, int nStart, /* out */int& nEnd );
- /***********************************************************************/
- /* 函數作用:向指定buffer裡寫入任意一段數據 */
- /* 參數pBuffer[in]:指定buffer */
- /* 參數tData[in]:需要寫入的數據,支持任意數據類型 */
- /* 參數nStart[in]:指定位置 */
- /* 參數btLength[in]:讀取長度 */
- /* 參數nEnd[out]:返回結束位置 */
- /* 返回:void */
- /***********************************************************************/
- template<typename T>
- void WriteDataToBuffer( byte* pBuffer, T tData, int nStart, byte btLength, /* out */int& nEnd );
- /***********************************************************************/
- /* 函數作用:向指定buffer裡寫取一段字符串 */
- /* 參數pBuffer[in]:指定buffer */
- /* 參數pchar[in]:需要寫入的字符串 */
- /* 參數nStart[in]:指定位置 */
- /* 參數nCount[in]:字符串長度 */
- /* 參數nEnd[out]:返回結束位置 */
- /* 返回:void */
- /***********************************************************************/
- void WtriteStringToBuffer( byte* pBuffer, char* pchar, int nStart, int nCount, /* out */int& nEnd );
//以下為函數實現
- void ReadOneBit( byte* pBuffer, int nStart, /* out */int& nEnd, /* out */ byte& retByte )
- {
- byte btData = pBuffer[nStart/8];
- btData = btData << nStart%8;
- retByte = btData >> 7;
- nEnd = nStart+1;
- }
- template<typename T>
- void ReadDataFromBuffer( byte* pBuffer, int nStart, byte btLength, /* out */int& nEnd, /* out */ T& retData )
- {
- //順序讀位
- retData = 0;
- if ( btLength > sizeof(T)*8 )
- return ;
- byte btData;
- T tData;
- while ( btLength-- )
- {
- ReadOneBit(pBuffer, nStart, nStart, btData);
- tData = btData << btLength;
- retData |= tData;
- }
- nEnd = nStart;
- }
- void ReadStringFromBuffer( byte* pBuffer, int nStart, int nCount, /* out */int& nEnd, /* out */char* pRetData )
- {
- for ( int nIndex=0; nIndex<nCount; nIndex++ )
- {
- ReadDataFromBuffer(pBuffer, nStart, 8, nStart, pRetData[nIndex]);
- }
- nEnd = nStart;
- }
- void WriteOneBit( byte* pBuffer, byte btData, int nStart, /* out */int& nEnd )
- {
- int nSet = nStart / 8;
- byte c = pBuffer[nSet];
- switch ( btData )
- {
- case 1:
- c |= ( 1 << (7- nStart % 8) );
- break;
- case 0:
- c &= ( ~(1 << (7- nStart % 8) ) );
- break;
- default:
- return;
- }
- pBuffer [nSet] = c;
- nEnd = nStart +1;
- }
- template<typename T>
- void WriteDataToBuffer( byte* pBuffer, T tData, int nStart, byte btLength, /* out */int& nEnd )
- {
- /* //大端機模式
- byte btDataLength = sizeof(T);
- if ( btLength > sizeof(T)*8 )
- return;
- int nDataStart = 0; //數據的第一位位置為0,順序寫入
- while ( btLength-- )
- {
- byte bitData;
- ReadOneBit((byte*)&tData, nDataStart, nDataStart, bitData);
- WriteOneBit(pBuffer, bitData, nStart, nStart);
- }
- nEnd = nStart;
- */
- //小端機模式:寫buffer的時候,不能順序寫位
- //獲得模版占用字節大小
- byte btDataLength = sizeof(T);
- //校驗長度是否越界
- if ( btLength > sizeof(T)*8 )
- return;
- //將待寫數據轉為byte*
- byte* ptData = (byte*)&tData;
- //求模與余
- int nSet = btLength / 8;
- int nRin = btLength % 8;
- //定義字節數據與位數據
- byte bitData;
- byte byteData;
- int nTempEnd;
- //先寫rin數據
- byteData = ptData[nSet];
- while ( nRin-- )
- {
- ReadOneBit(&byteData, 7-nRin, nTempEnd, bitData);
- WriteOneBit(pBuffer, bitData, nStart, nStart);
- }
- //再寫Set數據
- while ( nSet )
- {
- byteData = ptData[--nSet];
- //寫一個byte
- int i=0;
- while ( i!=8 )
- {
- ReadOneBit(&byteData, i++, nTempEnd, bitData);
- WriteOneBit(pBuffer, bitData, nStart, nStart);
- }
- }
- nEnd = nStart;
- }
- void WtriteStringToBuffer( byte* pBuffer, char* pchar, int nStart, int nCount, /* out */int& nEnd )
- {
- for ( int nIndex=0; nIndex<nCount; nIndex++ )
- {
- WriteDataToBuffer(pBuffer, pchar[nIndex], nStart, 8, nStart);
- }
- nEnd = nStart;
- }
本文出自 “鄒輝” 博客,請務必保留此出處http://zouhui.blog.51cto.com/3827922/776749