DLL工具函数base64转码、utf-8编码转换以及UUID随机数生成算法实现

通过C语言实现base64转码解码和utf-8编码转换以及UUID随机数获取的工具函数

概述

C语言的的DLL是一个很好用的东西,很多过程以及实现都可以自己控制,很多语言也都支持DLL动态链接库的读取和使用,最近接触了下,让我对算法有了更深的理解。

语言环境

  1. C语言,32位和64位可根据自己需求在编辑器上进行选择
  2. 这里使用的DEV C++可发工具
  3. 头文件:
    #include “dll.h”
    #include <stdio.h>
    #include <stdlib.h>
    #include <windows.h>
    #include <string.h>
    #include <wchar.h>
    #include <assert.h>
    #include <locale.h>

功能说明

  1. base64编码常用于数据数据传输过程,可作为图片或者其他数据的字节流传输形式,通过转码和解码,也在一定程度上保证了信息的安全和不可见,另外以字符形式存储避免了中文传输问题;后文提供转码和解码的详细逻辑和注释。
  2. utf-8是一种编码格式,使用很广泛,我是在某个API接口服务使用时用到的;后文给出其与Unicode编码的互转逻辑

实现代码

函数:Base64与字符串互转

/**
字符串转base64码 编码 
**/ 
__declspec(dllexport) unsigned char* __stdcall StrBase64(unsigned char *str)
{
	//定义base64编码表 
	unsigned char *base64_table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 
	
	long len;			//转换后字符串长度 
    long str_len;		//转换前字符长度 
    unsigned char *out;	//转换后字符串 
    int i,j;			//角标序号 i:转换前字符串 j:转换后字符串 
    
    //计算字符串长度 转换前
	str_len = strlen(str);
	//计算字符串长度 转换后 
	len = ((str_len + 2) / 3) * 4 ; 
	//定义动态字符数组用于存放base64码
	out = (unsigned char *)malloc(sizeof(unsigned char)*len+1);
	//录入末尾结束符
	out[len] = '\0';
	
	//字符串转base64码 3*8 = 4*6
	for(i=0,j=0;j<len-2;i+=3,j+=4){
		out[j] = base64_table[str[i]>>2];//第一个
		out[j+1] = base64_table[((str[i]&0x3)<<4) | (str[i+1]>>4)];//第二个
		out[j+2] = base64_table[((str[i+1]&0xf)<<2) | (str[i+2]>>6)];//第三个
		out[j+3] = base64_table[str[i+2]&0x3f];//第四个 
	}
	
	//补充不足字符,依据字符串除以3取余的情况赋值 
    switch(str_len % 3)  
    {  
        case 1:  
            out[j-2]='=';  
            out[j-1]='=';
            break;  
        case 2:  
            out[j-1]='=';  
            break; 
    }
	return out;
}
/**
base64码转字符串 解码 
**/ 
DLLIMPORT unsigned char* __stdcall Base64Str(unsigned char *base)
{
	//转码规则 base64码字符对应ASCII的二进制-十进制以确定位置然后取到base64编码规范中对应的value值以还原初始字符串对应二进制-十进制值
	//base64--ASCII(十进制值)--原始数据(十进制值)  共123个值,122-z最后一个 
	int table[]={
					0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
    				0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
    		 		0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,	0,
    		 		0,	0,	0,	0,	0,	0,	0,	62,	0,	0,	0,	63,
					52,	53,	54,	55,	56,	57,	58,	59,	60,	61,	0,	0,
					0,	0,	0,	0,	0,	0,	1,	2,	3,	4,	5,	6,
					7,	8,	9,	10,	11,	12,	13,	14,	15,	16,	17,	18,
					19,	20,	21,	22,	23,	24,	25,	0,	0,	0,	0,	0,
					0,	26,	27,	28,	29,	30,	31,	32,	33,	34,	35,	36,
					37,	38,	39,	40,	41,	42,	43,	44,	45,	46,	47,	48,
					49,	50,	51
				}; 
	long base_len;//base64字符串长度
	long str_len;//原始字符串长度
	unsigned char *str;//原始字符串
	int i,j;//角标序号 i:原始字符串 j:base64字符串
	
	//计算base64字符串长度 
	base_len = strlen(base);
	//判断"="字符的个数,以确定原字符串长度 
	if(strstr(base,"==")){
		str_len = (base_len/4)*3 - 2;
	} else if(strstr(base,"=")) {
		str_len = (base_len/4)*3 - 1;
	} else {
		str_len = (base_len/4) * 3;
	}
	
	//定义动态字符数组用于存放base64码
	str = (unsigned char *)malloc(sizeof(unsigned char)*str_len+1);
	//录入末尾结束符	
	str[str_len]='\0'; 
	
	//4*6 = 3*8 解码
	for(i=0,j=0;j<base_len-2;i+=3,j+=4){
		str[i] = ((table[base[j]]<<2) | (table[base[j+1]]>>4));//第一个值,ASCII十进制对应的图像符号
		str[i+1] = ((table[base[j+1]]<<4) | (table[base[j+2]]>>2));//第二个值
		str[i+2] = ((table[base[j+2]]<<6) | (table[base[j+3]]));//第三个值 
	}
	
	return str;
}

函数:UTF-8编码格式转换

/**
ACSII转utf-8的内部方法,供其他方法函数调用
**/
int AsciToUtf8(char* pSrc, char* pBuffer, unsigned int nBufferLen)
{
    assert(pSrc != NULL);
    
    unsigned int nSrcLen = lstrlen(pSrc) + 1;
    int nRet = 0;
    int nUtf16Len = MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLen, NULL, 0);
    if(nUtf16Len > 0)
    {
        wchar_t* pW ;//= new wchar_t[nUtf16Len];
        pW = (wchar_t*)malloc(sizeof(wchar_t*)*nUtf16Len);
        if(pW != NULL)
        {
            nUtf16Len = MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLen, pW, nUtf16Len);
             
            if(pBuffer == NULL || nBufferLen <= 0)
            {
                nRet = WideCharToMultiByte(CP_UTF8, 0, pW, nUtf16Len, NULL, 0, NULL, NULL);
            }
            else
            {
                nRet = WideCharToMultiByte(CP_UTF8, 0, pW, nUtf16Len, pBuffer, nBufferLen, NULL, NULL);
            }
 
            free(pW);
            pW = NULL;
        }
    }
 
    return nRet;
}

/**
ASCII码转UTF-8 
**/
DLLIMPORT unsigned char* __stdcall AscIIOrUtf(unsigned char *acs){
    int nLen = lstrlen(acs) + 1; //
    int nBufferLen = AsciToUtf8(acs, NULL, 0); 
    char* pBuffer;
    pBuffer = (char*)malloc(sizeof(char*)*nBufferLen);
    AsciToUtf8(acs,pBuffer, nBufferLen);
    return pBuffer;
}

/**
utf-8转ASCII或者Unicode编码 
**/
DLLIMPORT unsigned char* __stdcall Utf8ToAsci(unsigned char* pSrc)
{
	setlocale(LC_ALL, "");
    assert(pSrc != NULL);
    int wcsLen = MultiByteToWideChar(CP_UTF8, 0, pSrc, strlen(pSrc), NULL, 0);
    wchar_t* ph ;
    ph = (wchar_t*)malloc(sizeof(wchar_t*)*wcsLen+1);
    
    MultiByteToWideChar(CP_UTF8, 0, pSrc, strlen(pSrc), ph, wcsLen);//此处已经转换过来了 
    
    ph[wcsLen] = '\0';
    
    unsigned char* pBuffer;
    
    int len = strlen(pSrc);//此处使用该长度是为了防治数据溢出的异常,会比实际有效字符长度略大,汉子越多差距越大
    
    pBuffer = (unsigned char*)malloc(sizeof(unsigned char*)*len + 1);
    
    //pBuffer[len] = '\0';//可加可不加,因为在后面赋值时'\0'结束符同样会赋值给pBuffer
    
	//wcstombs(pBuffer,ph,strlen(pSrc));
	sprintf(pBuffer, "%ls", ph);//ls或S 
	//最终pBuffer的有效长度等于实际长度
	free(ph);//释放
	return pBuffer;
}

函数:生成随机数,同UUID随机数,32个字符

/**
生成随机数UUID 
**/
DLLIMPORT unsigned char* __stdcall UUIDStr(){
	unsigned char *buf;
	buf = (unsigned char *)malloc(sizeof(unsigned char)*36+1);
	buf[36] = '\0';
	const char *c = "89ab";
    char *p = buf;
    int n;
  
    for( n = 0; n < 16; ++n )
    {
        int b = rand()%255;
        switch( n )
        {
            case 6:
                sprintf(
                    p,
                    "4%x",
                    b%15 );
                break;
            case 8:
                sprintf(
                    p,
                    "%c%x",
                    c[rand()%strlen( c )],
                    b%15 );
                break;
            default:
                sprintf(
                    p,
                    "%02x",
                    b );
                break;
        }
        p += 2;
        switch( n )
        {
            case 3:
            case 5:
            case 7:
            case 9:
                //*p++ = '-';//这时buf含有值32+4+‘\0’,需要过滤‘-’ 
                break;
        }
    }
    *p = 0;
    return buf;
}

小贴士

1、对于C语言中char *型数据,在支持string(字符串类型)的语言中可直接使用string类型,如PB。
2、注意指针类型内存的释放。
3、注意数据的初始化

另外,本文也参照学习了网上其他博主的想法和代码,但在语言环境上面不够完善,不适用于C语言,所以本文在本地实现时做了部分更改,完全适用于C语言环境。
引用连接:
https://blog.csdn.net/weixin_30426957/article/details/95842873
https://blog.51cto.com/11998200/1867446

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值