linux 宽字符与多字节字符之间的转换

最近再调linux下证书验证问题,由于要对客户端发送过来的证书在服务器上与根证书进行认证,所以在读取证书、验证证书时设计到了编码转换问题。在windows下,使用MultiByteToWideChar和WideCharToMultiByte没有问题,但在linux下,不存在这两个函数,于是我们想到了用wcstombs和mbstowcs两个函数,但经试验,不能得到正确的结果,后来,经分析,得到,在windows下wchar_t为2字节,而在linux wchar_t为4字节,我们提取的证书编码为2字节的宽字符,所以不能正确地进行转换。不得不,只能使用libiconv进行转换。

iconv函数族的头文件是iconv.h。
#include
iconv函数族有三个函数,原型如下:
(1) iconv_t iconv_open(const char *tocode, const char *fromcode);
此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。
(2) size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);
此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。 (3) int iconv_close(iconv_t cd);
此函数用于关闭转换句柄,释放资源。

经过测试,使用这转换函数需要注意的有以下几点:

1、宽字节存在big-endian和little-endian之分,那使用宽字符编码时使用的编码名字也不一样,例如我们用的UCS-2编码,那有“UCS-2”和“UCS-2-INTERNAL”之分;

2、iconv中的两个长度在运行完函数后,分别为分配缓存剩余字节的大小;

3、而两个指针分别指向转换后字符串的尾部,所以在进行转换之前,应该保留缓存的原始指针,在转换后,用这两个指针减去原始指针,那就是已转换的字节长度和转换后的字节长度。

下面是我测试的代码,程序写的不怎么考究,呵呵!

 

#include
#include
#include
#include
#include
 
#define BUFLEN 200
char outBuf[BUFLEN];
//char inBuf[BUFLEN]="CN";
char inBuf[BUFLEN]="/x43/x00/x4e/x00/x00/x00";
//char inBuf[BUFLEN]="/x7a/x7a/x51/x9b/x00/x00";
 
int main(){
 
        char *pIn = inBuf;
        char *pOut = outBuf;
        iconv_t cd;
        int inLen = 4, outLen = BUFLEN;
        int retSize = 0;
 
        cd = iconv_open("UTF-8","UCS-2-INTERNAL");
//      cd = iconv_open("UCS-2-INTERNAL","UTF-8");
        if ((iconv_t)-1 == cd){
                printf("Donot support this convert../n");
                return -1;
        }
        if ((size_t)-1 == (retSize= iconv(cd, &pIn, (size_t *)&inLen, &pOut,(size_t *)&outLen))){
                if (E2BIG == errno)
                        printf(" E2BIG errno %d/n", errno);
                if (EILSEQ == errno)
                        printf("EILSEQ errno %d/n", errno);
                if (EINVAL == errno)
                        printf("EINVAL errno %d/n", errno);
                printf("convert WCHAR to multi error/n");
                return -1;
        }
 
        if (outLen > 0){
 
                printf("/n/n outBuf:");
                int i = 0;
                for (i = 0; i < 200; i++){
                        printf("%02x ", outBuf[i]);
                }
                printf("/n/n inBuf:");
                for (i = 0; i < 200; i++){
                        printf("%02x ", inBuf[i]);
                }
                printf("/n/n");
        }
        printf("out buf: %s outLen: %d retSize: %d inLen: %d/n", pOut, outLen, retSize, inLen);
        printf("pInbuf: %s/n", pIn);
        iconv_close(cd);
        return 0;
}

 

 

你可能感兴趣的:(linux 宽字符与多字节字符之间的转换)