字符流与字节流的相互转换原理及代码(Linux C)


  我们在做项目时,常常会遇到将字节流的数据转成字符流,或者将字符流的数据转为字节流,例如最近做的一个项目,其中一个模块是使用移远的EC20 4G模块通过串口编程实现中英文短信的发送与接收,其中:

  1. 在中文短信的发送时,要进行PDU的编码,其中包括了utf-8转unicode的处理,获取到的是字节流的unicode编码,但PDU格式是要求给串口发送字符流的数据,所以会使用的字节流转换为字符流的相关操作
  2. 在获取模块接收到的短信时,获取到的是一个字符流形式的unicode编码,编码我们是读不出来任何短信内容的,所以这是需要将unicode编码转为utf-8的编码才能打印并获取到短信内容,就需要在转码之前,将字符流的unicode编码转为字节流,因为字符流其本质是保存了相应字符的ASCII码值,并不能用来进行转码

下面就来看是是转换的原理和代码吧~

一. 两者的区别

  1. 字节流操作的基本单元为字节;字符流操作的基本单元为Unicode码元。

  2. 字节流默认不使用缓冲区;字符流使用缓冲区。

  3. 字节流通常用于处理二进制数据,实际上它可以处理任意类型的数据,但它不支持直接写入或读取Unicode码元;字符流通常处理文本数据,它支持写入及读取Unicode码元。

  4. 底层设备永远只接受字节数据,有时候要写字符串到底层设备,需要将字符串转成字节再进行写入。字符流是字节流的包装,字符流则是直接接受字符串,它内部将串转成字节,再写入底层设备,这为我们向IO设别写入或读取字符串提供了一点点方便。

二. 还需要了解

ASCII编码对照表

通过ASCII码对照表我们可以知道,要想获取到数值对应字符(如0x0a 对应的是字符‘0’ 和字符 ‘a’),以及反过来的字符对应的数值(如字符‘9’的数值是0x39),需要进行相关的加减法,还需要注意的是,字符’0’~‘9’后是7个符号,之后才是字符’A’~‘Z’,
在这里插入图片描述
在这里插入图片描述

三. 字节流转字符流实现

每个字节流数据都对应了两个字符就数据,如0xfe 对应了字符 ’ f ‘,’ e '.

/* 
 * 函数名:void Hex2Str(const char *source, int source_len, char *dest)
 * 功能  :将字节流的数据转为字符流形式
 * 参数  :source - 字节流数据      source_len - 长度       dest - 用来保存转换后的字符流数据
 * 返回值:无
 * 
 * */ 
void Hex2Str(const char *source, int source_len, char *dest)
{
    int      i;

    unsigned char     HighByte;  //保存高位
    unsigned char     LowByte;   //保存低位

    for(i=0; i<source_len; i++)
    {
        HighByte = source[i] >> 4;    //获取一个字节数据的高4位
        LowByte = source[i] & 0x0f;   //获取一个字节数据的低4位

        HighByte += 0x30;             //得到对应的字符,若是字母还需要跳过7个符号
        if(HighByte <= 0x39)          //数字
            dest[i*2] = HighByte;

        else                          //字母
            dest[i*2] = HighByte + 0x07;     //得到字符后保存到对应位置


        LowByte += 0x30;
        if(LowByte <= 0x39)
            dest[i*2+1] = LowByte;

        else
            dest[i*2+1] = LowByte + 0x07;

    }
    
    return;
}

三. 字符流转字节流实现

字符流的数据中,两个字符转为一个字节流数据,如字符串"1afd3c",可转为数值0x1a,0xfd,0x3c

/* 
 * 函数名:void Str2Hex(const char *source,int source_len,char *dest)
 * 功能  :将字符流的数据转为字节流形式
 * 参数  :source - 字符流数据      source_len - 长度       dest - 用来保存转换后的字节流数据
 * 返回值:无
 *
 * */
void Str2Hex(const char *source,int source_len,char *dest)
{
    int         i;
    unsigned char     HighByte;    //保存高位
    unsigned char     LowByte;     //保存低位

    for(i=0; i<source_len; i++)
    {
        HighByte = toupper(source[i*2]);    //如果遇到小写,则转为大写处理
        LowByte = toupper(source[i*2+1]);

        if(HighByte <= 0x39)       //0x39对应字符'9',这里表示是数字
            HighByte -= 0x30;

        else                      //否则为字母,需要跳过7个符号
            HighByte -= 0x37;

        if(LowByte <= 0x39)
            LowByte -= 0x30;

        else
            LowByte -= 0x37;

/*
 *  假设字符串"3c"
 *  则 HighByte = 0x03,二进制为 0000 0011 
 *     LowByte = 0x0c,二进制为 0000 1100
 *      
 *      HighByte << 4 = 0011 0000
 *      HighByte | LowByte :
 *      
 *      0011 0000
 *      0000 1100
 *    -------------
 *      0011 1100
 *
 *      即 0x3c
 *      
 **/
        dest[i] = (HighByte << 4) | LowByte;    

    }
}

四. 测试程序

4.1 头文件

/********************************************************************************
 *      Copyright:  (C) 2020 LuXiaoyang<920916829@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  String_Bytes.h
 *    Description:  This head file 
 *
 *        Version:  1.0.0(30/07/20)
 *         Author:  LuXiaoyang <920916829@qq.com>
 *      ChangeLog:  1, Release initial version on "30/07/20 16:58:45"
 *                 
 ********************************************************************************/
#ifndef  _STRING_BYTES_H_
#define  _STRING_BYTES_H_

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define BUFLENGTH 32



/* 字节流转字符流 */
void Hex2Str(const char *source, int source_len, char *dest);

/* 字符流转字节流 */
void Str2Hex(const char *source,int source_len,char *dest);



#endif   /* ----- #ifndef _STRING_BYTES_H_  ----- */

4.2 用于测试的程序

/*********************************************************************************
 *      Copyright:  (C) 2020 LuXiaoyang<920916829@qq.com>
 *                  All rights reserved.
 *
 *       Filename:  main.c
 *    Description:  This file a
 *                 
 *        Version:  1.0.0(30/07/20)
 *         Author:  LuXiaoyang <920916829@qq.com>
 *      ChangeLog:  1, Release initial version on "30/07/20 17:03:36"
 *                 
 ********************************************************************************/
#include "String_Bytes.h"


int main(int argc, char *argv[])
{
    int       i;
    char      String[BUFLENGTH] = "3c5d6cfecd4c";
    char      Hexstring[BUFLENGTH] = {0};
    char      String2[BUFLENGTH] = {0};

    Str2Hex(String,strlen(String),Hexstring);

    for(i=0; i < strlen(String)/2; i++)
    {
        printf("0x%02x  ",Hexstring[i]);
    }

    printf("\n");

    Hex2Str(Hexstring,strlen(String)/2,String2);

    printf("%s\n",String2);

    return 0;

}

4.2 简单写一个makefile

CC = gcc


main: main.c String_Bytes.o
    $(CC) main.c String_Bytes.o -o main 


String_Bytes.o: String_Bytes.c
    $(CC) -c String_Bytes.c


clean:
    rm *.o main
             

4.3 运行

在这里插入图片描述

像这样封装好函数,以后要用到的就直接把头文件c文件拷贝就可以直接调用函数了,也可以和其他自定义的字符串相关函数封装生成一个动态库使用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值