linux 宽字符与多字节字符之间的转换
最近再调linux下证书验证问题,由于要对客户端发送过来的证书在服务器上与根证书进行认证,所以在读取证书、验证证书时设计到了编码转换问题。在windows下,使用MultiByteToWideChar和WideCharToMultiByte没有问题,但在linux下,不存在这两个函数,于是我们想到了用wcstombs和mbstowcs两个函数,但经试验,不能得到正确的结果,后来,经分析,得到,在w
最近再调linux下证书验证问题,由于要对客户端发送过来的证书在服务器上与根证书进行认证,所以在读取证书、验证证书时设计到了编码转换问题。在windows下,使用MultiByteToWideChar和WideCharToMultiByte没有问题,但在linux下,不存在这两个函数,于是我们想到了用wcstombs和mbstowcs两个函数,但经试验,不能得到正确的结果,后来,经分析,得到,在windows下wchar_t为2字节,而在linux wchar_t为4字节,我们提取的证书编码为2字节的宽字符,所以不能正确地进行转换。不得不,只能使用libiconv进行转换。
iconv函数族的头文件是iconv.h。
#include <iconv.h>
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 <iconv.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <locale.h>
#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;
}
更多推荐
所有评论(0)