Linux C++ 字符串 编码识别、编码转换

 原文:http://blog.csdn.net/xian0617/article/details/6706107

最近在做一个类似垂直下载的爬虫系统。下载之后有个解析模块,解析之后要求编码一致的向后传入索引,便遇到了编码转换问题。

1. 编码的识别

  推荐使用 libchardet, 可以在这个页面下载,使用说明就算了,直接读头文件吧。

  这是一个简单的示例,嘿嘿。

  1. //#include "chardetect.h"   
  2. //char out_encode[CHARDET_MAX_ENCODING_NAME]   
  3.   
  4. char * EncodeUtil::GetLocalEncoding(const char* in_str, unsigned int str_len, char* out_encode){  
  5.     chardet_t chardect=NULL;  
  6.     if(chardet_create(&chardect)==CHARDET_RESULT_OK){  
  7.         if(chardet_handle_data(chardect, in_str, (unsigned int)str_len) == CHARDET_RESULT_OK)  
  8.             if(chardet_data_end(chardect) == CHARDET_RESULT_OK)  
  9.                 chardet_get_charset(chardect, out_encode, CHARDET_MAX_ENCODING_NAME);  
  10.     }  
  11.     if(chardect)  
  12.         chardet_destroy(chardect);  
  13.     return out_encode;  
  14. }  
//#include "chardetect.h"
//char out_encode[CHARDET_MAX_ENCODING_NAME]

char * EncodeUtil::GetLocalEncoding(const char* in_str, unsigned int str_len, char* out_encode){
	chardet_t chardect=NULL;
	if(chardet_create(&chardect)==CHARDET_RESULT_OK){
		if(chardet_handle_data(chardect, in_str, (unsigned int)str_len) == CHARDET_RESULT_OK)
			if(chardet_data_end(chardect) == CHARDET_RESULT_OK)
				chardet_get_charset(chardect, out_encode, CHARDET_MAX_ENCODING_NAME);
	}
	if(chardect)
		chardet_destroy(chardect);
	return out_encode;
}


 

  http://libibase.googlecode.com/files/libchardet-0.0.4.tar.gz

 

2.编码的转换

编码转换,当然要知道源编码和目的编码了,源编码可以使用1的方法获取,当然你必须相信他能检测出来大部分的编码。对于检测不出来的,你就根据应用来尝试几种编码吧。比如对于我的应用,当检测不到html源码的编码时,绝大部分情况下,UTF-8 尝试是正确的(使用浏览器进行先验的,嘿嘿)。 这里呢,有一个问题,就是Linux系统的iconv并不能完美的转码。特别是我发现很多被识别为UTF-8的竟然用iconv 转 GB 编码失败,于是乎,找到了iconv的升级版==>http://www.gnu.org/software/libiconv/ 。对,就是它!

下载、编译、安装、使用,嘿嘿,这个有文档,你慢慢看吧,哈哈。 下面是一个比较好用的使用示例,相信够用了。呵呵

  1. #ifndef ICONV_CONST   
  2. # define ICONV_CONST const   
  3. #endif   
  4.   
  5. int EncodeUtil::charsetConvert(const char *from_charset,const char *to_charset, const char *src, const int srclen, char* save,int savelen) {  
  6.   
  7.     if(save==NULL||srclen == 0) {  
  8.         return -1;  
  9.     }  
  10.   
  11.     save[0] = 0;  
  12.     if (strcmp(from_charset, to_charset) == 0) {  
  13.         if(savelen<=srclen)  
  14.             strncat(save, src, savelen);  
  15.         else  
  16.             strncat(save, src, srclen);  
  17.         return savelen>srclen ? srclen : savelen;  
  18.     }  
  19.   
  20.     //convert   
  21.     iconv_t cd;  
  22.     int status = 0; //result   
  23.     char *outbuf = save;//iconv outptr begin   
  24.     ICONV_CONST char* inptr = src;  
  25.     char* outptr = outbuf;  
  26.     size_t insize = srclen;  
  27.     size_t outsize = savelen;  
  28.   
  29.     cd = iconv_open(to_charset, from_charset);  
  30.     if((iconv_t)(-1) == cd){  
  31.         return -1;  
  32.     }  
  33.     iconv(cd, NULL, NULL, NULL, NULL);  
  34.     while (insize > 0) {  
  35.         size_t res = iconv(cd, (ICONV_CONST char**) &inptr, &insize, &outptr,&outsize);  
  36.         if (outptr != outbuf) {  
  37.             outbuf=outptr;  
  38.             *outbuf=0;  
  39.         }  
  40.         if (res == (size_t) (-1)) {  
  41.             if (errno == EILSEQ) {  
  42.                 int one = 1;  
  43.                 iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &one);  
  44.                 status = -3;  
  45.             } else if (errno == EINVAL) {  
  46.                 if (srclen == 0) {  
  47.                     status = -4;  
  48.                     goto done;  
  49.                 } else {  
  50.                     break;  
  51.                 }  
  52.             } else if (errno == E2BIG) {  
  53.                 status = -5;  
  54.                 goto done;  
  55.             } else {  
  56.                 status = -6;  
  57.                 goto done;  
  58.             }  
  59.         }  
  60.     }  
  61.     status = strlen(save);// ===  outbuf - save ;   
  62. done:  
  63.     iconv_close(cd);  
  64.     return status;  
  65. }  
#ifndef ICONV_CONST
# define ICONV_CONST const
#endif

int EncodeUtil::charsetConvert(const char *from_charset,const char *to_charset, const char *src, const int srclen, char* save,int savelen) {

	if(save==NULL||srclen == 0) {
		return -1;
	}

	save[0] = 0;
	if (strcmp(from_charset, to_charset) == 0) {
		if(savelen<=srclen)
			strncat(save, src, savelen);
		else
			strncat(save, src, srclen);
		return savelen>srclen ? srclen : savelen;
	}

	//convert
	iconv_t cd;
	int status = 0; //result
	char *outbuf = save;//iconv outptr begin
	ICONV_CONST char* inptr = src;
	char* outptr = outbuf;
	size_t insize = srclen;
	size_t outsize = savelen;

	cd = iconv_open(to_charset, from_charset);
	if((iconv_t)(-1) == cd){
		return -1;
	}
	iconv(cd, NULL, NULL, NULL, NULL);
	while (insize > 0) {
		size_t res = iconv(cd, (ICONV_CONST char**) &inptr, &insize, &outptr,&outsize);
		if (outptr != outbuf) {
			outbuf=outptr;
			*outbuf=0;
		}
		if (res == (size_t) (-1)) {
			if (errno == EILSEQ) {
				int one = 1;
				iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &one);
				status = -3;
			} else if (errno == EINVAL) {
				if (srclen == 0) {
					status = -4;
					goto done;
				} else {
					break;
				}
			} else if (errno == E2BIG) {
				status = -5;
				goto done;
			} else {
				status = -6;
				goto done;
			}
		}
	}
	status = strlen(save);// ===  outbuf - save ;
done:
    iconv_close(cd);
	return status;
}

 
 

需要唠叨一句,不知道为什么,为什么这么底层的接口竟然 src 不用const 修饰,所以我传进来的const char *src 实际在函数中是有警告的,无奈,忽略吧。

 

3.OK ,结束了。哈哈。贴上一个多余的玩意儿,就是我的系统实际访问的接口。

  1. int EncodeUtil::ConvertToGb(const char* in_str, int str_len,char* out_str, int out_str_len){  
  2.     char encode[CHARDET_MAX_ENCODING_NAME];  
  3.     encode[0]=0;  
  4.     GetLocalEncoding(in_str,str_len,encode);  
  5.     if(encode[0]==0){  
  6.         //I'll try UTF-8 ,If you think it dosn't matter about undetect encode ,return -1 is ok   
  7.         sprintf(encode,"%s","UTF-8");  
  8.         //return -1;   
  9.     }  
  10.   
  11.     return charsetConvert(encode,"GB18030",in_str,str_len,out_str,out_str_len);  
  12. }  
int EncodeUtil::ConvertToGb(const char* in_str, int str_len,char* out_str, int out_str_len){
	char encode[CHARDET_MAX_ENCODING_NAME];
	encode[0]=0;
	GetLocalEncoding(in_str,str_len,encode);
	if(encode[0]==0){
		//I'll try UTF-8 ,If you think it dosn't matter about undetect encode ,return -1 is ok
		sprintf(encode,"%s","UTF-8");
		//return -1;
	}

	return charsetConvert(encode,"GB18030",in_str,str_len,out_str,out_str_len);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值