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

来源:互联网 发布:淘宝服装店店铺介绍 编辑:程序博客网 时间:2024/06/05 04:30

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

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

1. 编码的识别

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

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

[cpp] view plaincopyprint?
  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. }  


 

  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/ 。对,就是它!

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

[cpp] view plaincopyprint?
  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. }  

 

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

 

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

[cpp] view plaincopyprint?
  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. }