字节流与位流的相互转换实现

来源:互联网 发布:淘宝注册多少钱 编辑:程序博客网 时间:2024/06/05 18:35

字节流与位流的相互转换实现

 引言:在项目开发中,我们会遇到字节流与比特流相互转换、逐字节、逐位操作的场景。没有现成的库供我们调用,需要我们自己实现之。

一、字节流、位流介绍

       【维基百科--字节流】:在计算机科学里面,字节流(byte stream)是一种位流,不过里面的比特被打包成一个个我们叫做字节Bytes)的单位。

       【字节流范例】:在网络传输协议里面比较有名,且会提供字节流给客户端的范例是TCP/IP通讯协定里面的传输控制协议TCP),这种协议提供了双向的字节流。

       【维基百科--位元流】:一个位元流(bitstreambit stream)是一个位元序列。一个字节流则是一个字节的序列,一般来说一个字节是8个位元。也可以被视为是一种特殊的位元流。

        【位元流范例】:位元流在远程通信计算这些领域里面被广泛的使用:举例来说,同步光网络通信科技会传输同步位元流。

         在项目的开发中,我们经常会遇到对于给定的字符串“0123456789abcdef”(字节流,16个字节),我们需要其转化为对应的二进制位流(其中0对应的ASCII码元为0x30,对应二进制为00110000,一个字节用8个二进制模拟输出,合计16*8=128个二进制数据)。

         没有现成的库函数供我们调用,所以考虑字节流的特点,加上位元算的操作,以下是其相互转换的完整的实现及测试用例。

二、字节流转为位流的核心操作——如何获取到每一位

       方法:通过右移操作,然后与10000 0001)求与的方式。

       如下表所示,依次实现0x30右移动(1,2,3,4…)位,然后与0000 0001进行与操作;显然,只有当移动到的末位为1时两者与操作才为1(右移动4位),其他都为0。如:

初始

右移0 >>0

0x30

00110000

右移1

右移1 >>1

0x18

00011000

右移2

右移2 >>2

0x0c

00001100

右移3

右移3 >>3

0x06

00000110

右移4

右移4 >>4

0x03

00000011

 

三、位流转为字节流的核心:如何将8位合为一个字节

比特流

字节流

0011 0000

0*128+0*64+1*32+1*16+0=48(10进制)=0x30(16进制)

          方法一:通过传统每位与基数相乘累计求和的方式实现。

          方法二:每8位一个单元,的方式模拟求和(与字节流转化为位流方法相反),详见代码。

四、位流与字节流相互转化的实现

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. #include <string.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h>  
  4. #include <assert.h>  
  5. #include <iostream>  
  6. using namespace std;  
  7.   
  8. #define  UCHAR  unsigned char  
  9. const int MULTIPLE = 8;       //字节流长度是位流的8倍  
  10. const int FIX_VAL = 0X01;     //求&专用特定值  
  11. const int g_BinArr[MULTIPLE] = {128,64,32,16,8,4,2,1}; //2的次幂  
  12.   
  13. /* 
  14. **@brief 字节流转为位流 
  15. **@param [in]puchByte,字节流;[in]iByteLen,字节流长度;  
  16.    [in&out]puchBit,位流; [in&out]iBitLen,位流长度 
  17. **@return 空 
  18. */  
  19. void byte_to_bit(const UCHAR *puchByte, const int& iByteLen, UCHAR *puchBit, int *pBitLen)  
  20. {  
  21.  assert(puchByte != NULL && iByteLen >0 && puchBit != NULL && pBitLen !=NULL);  
  22.    
  23.  int iBitLen = 0;  
  24.  for (int i = 0; i < iByteLen; i++)  
  25.  {  
  26.   for(int j = 0; j < MULTIPLE; j++)  
  27.   {  
  28.    //printf("%0x >> %d = %0x\n", puchByte[i], j, puchByte[i]>>j);  
  29.    puchBit[i*MULTIPLE + MULTIPLE - 1 - j] = ((puchByte[i])>>j)&FIX_VAL;  
  30.    iBitLen++;  
  31.   }//end for j  
  32.  }//end for   
  33.    
  34.  *pBitLen = iBitLen;  
  35. }  


 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2. **@brief 位流转为字节流 
  3. **@param [in]puchBit,位流;[in]iBitLen,位流长度;  
  4.    [in&out]puchByte,字节流 [in&out]pByteLen,字节流长度 
  5. **@return 空 
  6. */  
  7. void bit_to_byte(const UCHAR *puchBit, const int& iBitLen, UCHAR *puchByte, int* pByteLen)  
  8. {  
  9.  assert(puchBit && iBitLen > 0 && puchByte && pByteLen);  
  10.  int iByteNo = 0;    
  11.  int iBitInByte = 0;  
  12.  for(int i = 0; i < iBitLen; i++)  
  13.  {  
  14.   iByteNo = i/MULTIPLE;    //字节序号  
  15.   iBitInByte = i%MULTIPLE; //字节里的比特序号(0-7)  
  16.    
  17.   puchByte[iByteNo] += puchBit[i]*g_BinArr[iBitInByte];  //累计求和  
  18.     
  19.   //cout << "iByteNo =:" << iByteNo << "\t iBitInByte = " << iBitInByte \  
  20.   //<< "\t puchByte[iByteNo] = " << puchByte[iByteNo] << endl;  
  21.  }//end for i  
  22.  *pByteLen = iBitLen/MULTIPLE;  
  23. }  


 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2. **@brief 位流转为字节流[方法二] 
  3. **@param [in]puchBit,位流;[in]iBitLen,位流长度;  
  4.    [in&out]puchByte,字节流; [in&out]字节流长度 
  5. **@return 空 
  6. */  
  7. void bit_to_byte_ext(const UCHAR *puchBit, const int& iBitLen, UCHAR *puchByte, int* iByteLen)  
  8. {  
  9.  assert(puchBit && iBitLen > 0 && puchByte && iByteLen);  
  10.    
  11.  int iByteNo = 0;              //字节号  
  12.  UCHAR uchTmp = 0;   
  13.  for(int i = 0; i < iBitLen; i+=MULTIPLE)  
  14.  {  
  15.   for(int j = 0; j < MULTIPLE; j++)  
  16.   {  
  17.    //通过或的方式累计求和  
  18.    uchTmp |= ((puchBit[i + j])<<(MULTIPLE - 1 - j));  
  19.   }  
  20.   //printf("uchTmp = %0x\n",uchTmp);  
  21.   puchByte[iByteNo] = uchTmp;  
  22.     
  23.   iByteNo++;    //字节号+1  
  24.   uchTmp = 0;  
  25.  }//end for i  
  26.    
  27.  *iByteLen = iByteNo;  
  28. }  
  29.   
  30.   
  31.    
[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /* 
  2. **@brief 测试位流与字节流互转 
  3. **@param  空 
  4. **@return 空 
  5. */  
  6. void test_byte_bit()  
  7. {  
  8.  const UCHAR uchByte[] = "0123456789abcdef";        //原始字节流  
  9.  int iByteLen = sizeof(uchByte)/sizeof(UCHAR) - 1;  //原始字节流长度  
  10.  int iBitLen = MULTIPLE*iByteLen;                   //比特流长度  
  11.  UCHAR *puchBit = new UCHAR[iBitLen];  
  12.  memset(puchBit, 0, iBitLen);  
  13.    
  14.  cout << "原始字节流为: ";  
  15.  #if 0  
  16.  for (int i = 0; i < iByteLen; i++)  
  17.  {  
  18.   printf("%0x\t", uchByte[i]);                    
  19.  }  
  20.  printf("\n");  
  21.  #endif  
  22.  cout << uchByte << endl;  
  23.    
  24.  int iBitLenX = 0;  
  25.  byte_to_bit(uchByte, iByteLen, puchBit, &iBitLenX);  //字节转化为比特流  
  26.    
  27.  cout << "测试字节流转化过的位流为: " << endl;  
  28.  for (int i = 0; i < iBitLen; i++)  
  29.  {  
  30.   printf("%0x",puchBit[i]);  
  31.  }  
  32.  printf("\n");  
  33.  cout << "位流长度为: " << iBitLenX << endl << endl;  
  34.    
  35.  UCHAR* puchByte = new UCHAR[1 + iByteLen];  
  36.  memset(puchByte, 0, 1 + iByteLen);  
  37.  int iByteLenX = 0;  
  38.    
  39.  #if 1  
  40.  bit_to_byte(puchBit, iBitLen, puchByte, &iByteLenX);    //比特流转化字节流方法1  
  41.  #endif  
  42.    
  43.  #if 0  
  44.  bit_to_byte_ext(puchBit, iBitLen, puchByte, &iByteLenX); //比特流转化字节流方法2  
  45.  #endif  
  46.    
  47.  cout << "测试位流转化过的字节流为: " << endl;  
  48.   
  49.  for (i = 0; i < iByteLen; i++)  
  50.  {  
  51.   printf("%0x\t",puchByte[i]);  
  52.  }  
  53.  printf("\n");  
  54.   
  55.  cout << "位流转为成的字节流为: " << puchByte << endl;  
  56.  cout << "字节流的长度为: " << iByteLen << endl;  
  57.    
  58.  if (puchBit != NULL)  
  59.  {  
  60.   delete []puchBit;  
  61.   puchBit = NULL;  
  62.  }  
  63.  if (puchByte != NULL)  
  64.  {  
  65.   delete []puchByte;  
  66.   puchByte = NULL;  
  67.  }  
  68. }  
  69.   
  70. int main()  
  71. {  
  72.  test_byte_bit();  
  73.    
  74.  return 0;  
  75. }  


 

五、结语:

       根据代码走读,会加深对于字节流与位流相互转换的理解。

0 0
原创粉丝点击