前谈过一篇关于Linux下面Unicode使用的文章。那个主要是针对多字节和宽字符的转换而谈的。今天说的有些类似,主要是windows下面关于字符编码转换和Linux下面的不同。
我移植的那部分程序中,有函数是用来实现UTF-8和GBK之间的转换的。其实其他很多不同类型的字符之间转换都可以用这种方法。
先说windows。因为windows下面没有函数可以实现这一功能,所以得自己写。思路很简单,就是利用之前讲过的那两个函数来实现,即:MultiByteToWideChar和WideCharToMultiByte来实现。先将其中一种编码(如UTF-8)利用MultiByteToWideChar转换为宽字节,然后再利用WideCharToMultiByte转换为另一种编码(如GBK)。反过来也是一样的。
下面给出代码:
LONG UTF8ToGBK(const void * lpUTF8Str, string & str)
{
if(lpUTF8Str == NULL) return -1;
int nRetLen = 0;
//获取转换到Unicode编码后所需要的字符空间长度
nRetLen = ::MultiByteToWideChar(CP_UTF8, 0,
{
if(lpUTF8Str == NULL) return -1;
int nRetLen = 0;
//获取转换到Unicode编码后所需要的字符空间长度
nRetLen = ::MultiByteToWideChar(CP_UTF8, 0,
(char *)lpUTF8Str, -1, NULL, NULL);
WCHAR *lpUnicodeStr = new WCHAR[nRetLen + 1];
//为Unicode字符串空间
//转换到Unicode编码
nRetLen = ::MultiByteToWideChar(CP_UTF8, 0,
//转换到Unicode编码
nRetLen = ::MultiByteToWideChar(CP_UTF8, 0,
(char *)lpUTF8Str, -1, lpUnicodeStr, nRetLen);
if(!nRetLen)
{
delete []lpUnicodeStr; return -1;
}
//获取转换到GBK编码后所需要的字符空间长度
nRetLen = ::WideCharToMultiByte(CP_ACP, 0, lpUnicodeStr,
if(!nRetLen)
{
delete []lpUnicodeStr; return -1;
}
//获取转换到GBK编码后所需要的字符空间长度
nRetLen = ::WideCharToMultiByte(CP_ACP, 0, lpUnicodeStr,
-1, NULL, NULL, NULL, NULL);
CHAR *lpGBKStr = new CHAR[nRetLen + 1];
nRetLen = ::WideCharToMultiByte(CP_ACP, 0, lpUnicodeStr,
CHAR *lpGBKStr = new CHAR[nRetLen + 1];
nRetLen = ::WideCharToMultiByte(CP_ACP, 0, lpUnicodeStr,
-1, (char *)lpGBKStr, nRetLen, NULL, NULL);
//转换到GBK编码
if(!nRetLen)
{
delete []lpUnicodeStr;
delete []lpGBKStr;
return -2;
}
str = lpGBKStr;
delete []lpUnicodeStr;
delete []lpGBKStr;
return 0;
}
if(!nRetLen)
{
delete []lpUnicodeStr;
delete []lpGBKStr;
return -2;
}
str = lpGBKStr;
delete []lpUnicodeStr;
delete []lpGBKStr;
return 0;
}
再来看Linux,它已经提供了函数可以实现这一功能,不仅如此,Linux还可以实现批量文件的字符编码转换呢。只不过在Linux下面支持的字符集多少会和Windows的不同,所以一定得先查字符集有哪些,再去使用函数。这里推荐使用locale –m命令,得到的字符集比较全。
实现这一功能的正是iconv函数族,包含以下三个函数:
iconv_t iconv_open(const char *tocode, const char *fromcode);
此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。
此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。
size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);
此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。
此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间。
int iconv_close(iconv_t cd);
此函数用于关闭转换句柄,释放资源。
此函数用于关闭转换句柄,释放资源。
下面给demo代码:
#include <stdio.h>
#include <iconv.h>
#include <string.h>
#define BUFLEN 256
char outbuf[BUFLEN];
char inbuf[BUFLEN] = "characters convertion";
int main()
{
char *pin = inbuf;
char *pout = outbuf;
int inlen = strlen(pin);
int outlen = BUFLEN;
int retsize;
iconv_t cd;
cd = iconv_open("UTF-8", "GBK");
if((iconv_t)-1 == cd) {
perror("iconv_open error");
return -1;
}
retsize = iconv(cd, &pin, (size_t *)&inlen, &pout, (size_t *)&outlen);
if((size_t)-1 == retsize) {
perror("iconv error");
return -2;
}
if(outlen > 0) {
printf("%s\n", outbuf);
}
iconv_close(cd);
return 0;
}
#include <iconv.h>
#include <string.h>
#define BUFLEN 256
char outbuf[BUFLEN];
char inbuf[BUFLEN] = "characters convertion";
int main()
{
char *pin = inbuf;
char *pout = outbuf;
int inlen = strlen(pin);
int outlen = BUFLEN;
int retsize;
iconv_t cd;
cd = iconv_open("UTF-8", "GBK");
if((iconv_t)-1 == cd) {
perror("iconv_open error");
return -1;
}
retsize = iconv(cd, &pin, (size_t *)&inlen, &pout, (size_t *)&outlen);
if((size_t)-1 == retsize) {
perror("iconv error");
return -2;
}
if(outlen > 0) {
printf("%s\n", outbuf);
}
iconv_close(cd);
return 0;
}
本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/253385,如需转载请自行联系原作者