字节流与位流的相互转换实现
来源:互联网 发布:淘宝注册多少钱 编辑:程序博客网 时间:2024/06/05 18:35
字节流与位流的相互转换实现
引言:在项目开发中,我们会遇到字节流与比特流相互转换、逐字节、逐位操作的场景。没有现成的库供我们调用,需要我们自己实现之。
一、字节流、位流介绍
【维基百科--字节流】:在计算机科学里面,字节流(byte stream)是一种位流,不过里面的比特被打包成一个个我们叫做字节(Bytes)的单位。
【字节流范例】:在网络传输协议里面比较有名,且会提供字节流给客户端的范例是TCP/IP通讯协定里面的传输控制协议(TCP),这种协议提供了双向的字节流。
【维基百科--位元流】:一个位元流(bitstream或bit stream)是一个位元的序列。一个字节流则是一个字节的序列,一般来说一个字节是8个位元。也可以被视为是一种特殊的位元流。
【位元流范例】:位元流在远程通信和计算这些领域里面被广泛的使用:举例来说,同步光网络通信科技会传输同步位元流。
在项目的开发中,我们经常会遇到对于给定的字符串“0123456789abcdef”(字节流,16个字节),我们需要其转化为对应的二进制位流(其中0对应的ASCII码元为0x30,对应二进制为00110000,一个字节用8个二进制模拟输出,合计16*8=128个二进制数据)。
没有现成的库函数供我们调用,所以考虑字节流的特点,加上位元算的操作,以下是其相互转换的完整的实现及测试用例。
二、字节流转为位流的核心操作——如何获取到每一位
方法:通过右移操作,然后与1(0000 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位一个单元,”或”的方式模拟求和(与字节流转化为位流方法相反),详见代码。
四、位流与字节流相互转化的实现
- #include <string.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <assert.h>
- #include <iostream>
- using namespace std;
- #define UCHAR unsigned char
- const int MULTIPLE = 8; //字节流长度是位流的8倍
- const int FIX_VAL = 0X01; //求&专用特定值
- const int g_BinArr[MULTIPLE] = {128,64,32,16,8,4,2,1}; //2的次幂
- /*
- **@brief 字节流转为位流
- **@param [in]puchByte,字节流;[in]iByteLen,字节流长度;
- [in&out]puchBit,位流; [in&out]iBitLen,位流长度
- **@return 空
- */
- void byte_to_bit(const UCHAR *puchByte, const int& iByteLen, UCHAR *puchBit, int *pBitLen)
- {
- assert(puchByte != NULL && iByteLen >0 && puchBit != NULL && pBitLen !=NULL);
- int iBitLen = 0;
- for (int i = 0; i < iByteLen; i++)
- {
- for(int j = 0; j < MULTIPLE; j++)
- {
- //printf("%0x >> %d = %0x\n", puchByte[i], j, puchByte[i]>>j);
- puchBit[i*MULTIPLE + MULTIPLE - 1 - j] = ((puchByte[i])>>j)&FIX_VAL;
- iBitLen++;
- }//end for j
- }//end for
- *pBitLen = iBitLen;
- }
- /*
- **@brief 位流转为字节流
- **@param [in]puchBit,位流;[in]iBitLen,位流长度;
- [in&out]puchByte,字节流 [in&out]pByteLen,字节流长度
- **@return 空
- */
- void bit_to_byte(const UCHAR *puchBit, const int& iBitLen, UCHAR *puchByte, int* pByteLen)
- {
- assert(puchBit && iBitLen > 0 && puchByte && pByteLen);
- int iByteNo = 0;
- int iBitInByte = 0;
- for(int i = 0; i < iBitLen; i++)
- {
- iByteNo = i/MULTIPLE; //字节序号
- iBitInByte = i%MULTIPLE; //字节里的比特序号(0-7)
- puchByte[iByteNo] += puchBit[i]*g_BinArr[iBitInByte]; //累计求和
- //cout << "iByteNo =:" << iByteNo << "\t iBitInByte = " << iBitInByte \
- //<< "\t puchByte[iByteNo] = " << puchByte[iByteNo] << endl;
- }//end for i
- *pByteLen = iBitLen/MULTIPLE;
- }
- /*
- **@brief 位流转为字节流[方法二]
- **@param [in]puchBit,位流;[in]iBitLen,位流长度;
- [in&out]puchByte,字节流; [in&out]字节流长度
- **@return 空
- */
- void bit_to_byte_ext(const UCHAR *puchBit, const int& iBitLen, UCHAR *puchByte, int* iByteLen)
- {
- assert(puchBit && iBitLen > 0 && puchByte && iByteLen);
- int iByteNo = 0; //字节号
- UCHAR uchTmp = 0;
- for(int i = 0; i < iBitLen; i+=MULTIPLE)
- {
- for(int j = 0; j < MULTIPLE; j++)
- {
- //通过或的方式累计求和
- uchTmp |= ((puchBit[i + j])<<(MULTIPLE - 1 - j));
- }
- //printf("uchTmp = %0x\n",uchTmp);
- puchByte[iByteNo] = uchTmp;
- iByteNo++; //字节号+1
- uchTmp = 0;
- }//end for i
- *iByteLen = iByteNo;
- }
- /*
- **@brief 测试位流与字节流互转
- **@param 空
- **@return 空
- */
- void test_byte_bit()
- {
- const UCHAR uchByte[] = "0123456789abcdef"; //原始字节流
- int iByteLen = sizeof(uchByte)/sizeof(UCHAR) - 1; //原始字节流长度
- int iBitLen = MULTIPLE*iByteLen; //比特流长度
- UCHAR *puchBit = new UCHAR[iBitLen];
- memset(puchBit, 0, iBitLen);
- cout << "原始字节流为: ";
- #if 0
- for (int i = 0; i < iByteLen; i++)
- {
- printf("%0x\t", uchByte[i]);
- }
- printf("\n");
- #endif
- cout << uchByte << endl;
- int iBitLenX = 0;
- byte_to_bit(uchByte, iByteLen, puchBit, &iBitLenX); //字节转化为比特流
- cout << "测试字节流转化过的位流为: " << endl;
- for (int i = 0; i < iBitLen; i++)
- {
- printf("%0x",puchBit[i]);
- }
- printf("\n");
- cout << "位流长度为: " << iBitLenX << endl << endl;
- UCHAR* puchByte = new UCHAR[1 + iByteLen];
- memset(puchByte, 0, 1 + iByteLen);
- int iByteLenX = 0;
- #if 1
- bit_to_byte(puchBit, iBitLen, puchByte, &iByteLenX); //比特流转化字节流方法1
- #endif
- #if 0
- bit_to_byte_ext(puchBit, iBitLen, puchByte, &iByteLenX); //比特流转化字节流方法2
- #endif
- cout << "测试位流转化过的字节流为: " << endl;
- for (i = 0; i < iByteLen; i++)
- {
- printf("%0x\t",puchByte[i]);
- }
- printf("\n");
- cout << "位流转为成的字节流为: " << puchByte << endl;
- cout << "字节流的长度为: " << iByteLen << endl;
- if (puchBit != NULL)
- {
- delete []puchBit;
- puchBit = NULL;
- }
- if (puchByte != NULL)
- {
- delete []puchByte;
- puchByte = NULL;
- }
- }
- int main()
- {
- test_byte_bit();
- return 0;
- }
五、结语:
根据代码走读,会加深对于字节流与位流相互转换的理解。
- 字节流与位流的相互转换实现
- 字节流与位流的相互转换实现
- 字节流与位流的相互转换实现
- c#实现图片与字节流相互转换的代码
- C语言实现字节流与十六进制字符串的相互转换
- C语言实现字节流与十六进制字符串的相互转换
- C语言实现字节流与十六进制字符串的相互转换
- C语言实现字节流与十六进制字符串的相互转换
- C语言实现字节流与十六进制字符串的相互转换
- C语言实现字节流与十六进制字符串的相互转换
- C语言实现字节流与十六进制字符串的相互转换
- JAVA IO流实现字节数组与任何基本类型和引用类型的相互转换
- C语言实现字节流与十六进制字符串的相互转换
- C语言实现字节流与十六进制字符串的相互转换
- C语言实现字节流与十六进制字符串的相互转换
- 字节流与字符流的区别及相互转换
- JAVA字节流与字符流的相互转换
- JAVA字节流与字符流的相互转换
- 黑马程序员---Java基础学习之Java语法格式
- ios打电话
- gcd(int a, int b) //求最大公约数
- 画表格_蓝桥杯
- 黑马程序员---Java基础学习之Java关键字、保留字、标识符
- 字节流与位流的相互转换实现
- excelPOI导出
- 小知识
- 语言--c--空指针(NULL,0),野指针,void*的讲解
- typdef 与 #define
- coding----1wcods----坚持第4天----635行
- 黑马程序员---Java基础学习之Java的常量和进制
- Mac上彻底删除openfire
- 上传excel并处理