关闭

让Expat支持中文XML

6025人阅读 评论(0) 收藏 举报

在很多地方看到对一篇<如何让Expat支持中文XML>的文章,其中提到:

Expat并不支持中文,Expat不支持gb2312编码格式,主要支持UTF-8编码格式

两种解决办法:
    1、改写Expat源代码,这样效率高,但不方便今后Expat代码的升级;
    2、首先将gb2312格式的文本转换为UTF-8格式文本,然后让Expat解析,解析出的数据再转换为gb2312格式以方便处理。效率较第一种方法低。

第二中方法,在那篇文章中有提到,但是他给的连接却不能用,很是郁闷.所以自己找了格式装换的代码如下:

在LINUX上进行编码转换时,既可以利用iconv函数族编程实现,也可以利用iconv命令来实现,只不过后者是针对文件的,即将指定文件从一种编码转换为另一种编码。
利用iconv函数族进行编码转换
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: 用C语言实现的转换示例程序

/* f.c : 代码转换示例C程序 */
#include <iconv.h>
#define OUTLEN 255
main()
{
char *in_utf8 = "姝e?ㄥ??瑁?";
char *in_gb2312 = "正在安装";
char out[OUTLEN];

//unicode码转为gb2312码
rc = u2g(in_utf8,strlen(in_utf8),out,OUTLEN);
printf("unicode-->gb2312 out=%sn",out);
//gb2312码转为unicode码
rc = g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN);
printf("gb2312-->unicode out=%sn",out);
}
//代码转换:从一种编码转为另一种编码
int code_convert(char *from_charset,char *to_charset,char *inbuf,int inlen,char *outbuf,int outlen)
{
iconv_t cd;
int rc;
char **pin = &inbuf;
char **pout = &outbuf;

cd = iconv_open(to_charset,from_charset);
if (cd==0) return -1;
memset(outbuf,0,outlen);
if (iconv(cd,pin,&inlen,pout,&outlen)==-1) return -1;
iconv_close(cd);
return 0;
}
//UNICODE码转为GB2312码
int u2g(char *inbuf,int inlen,char *outbuf,int outlen)
{
return code_convert("utf-8","gb2312",inbuf,inlen,outbuf,outlen);
}
//GB2312码转为UNICODE码
int g2u(char *inbuf,size_t inlen,char *outbuf,size_t outlen)
{
return code_convert("gb2312","utf-8",inbuf,inlen,outbuf,outlen);
}

例子2: 用C++语言实现的转换示例程序

/* f.cpp : 代码转换示例C++程序 */
#include <iconv.h>
#include <iostream>

#define OUTLEN 255

using namespace std;

// 代码转换操作类
class CodeConverter {
private:
iconv_t cd;
public:
// 构造
CodeConverter(const char *from_charset,const char *to_charset) {
cd = iconv_open(to_charset,from_charset);
}

// 析构
~CodeConverter() {
iconv_close(cd);
}

// 转换输出
int convert(char *inbuf,int inlen,char *outbuf,int outlen) {
char **pin = &inbuf;
char **pout = &outbuf;

memset(outbuf,0,outlen);
return iconv(cd,pin,(size_t *)&inlen,pout,(size_t *)&outlen);
}
};

int main(int argc, char **argv)
{
char *in_utf8 = "姝e?ㄥ??瑁?";
char *in_gb2312 = "正在安装";
char out[OUTLEN];

// utf-8-->gb2312
CodeConverter cc = CodeConverter("utf-8","gb2312");
cc.convert(in_utf8,strlen(in_utf8),out,OUTLEN);
cout << "utf-8-->gb2312 in=" << in_utf8 << ",out=" << out << endl;

// gb2312-->utf-8
CodeConverter cc2 = CodeConverter("gb2312","utf-8");
cc2.convert(in_gb2312,strlen(in_gb2312),out,OUTLEN);
cout << "gb2312-->utf-8 in=" << in_gb2312 << ",out=" << out << endl;
}

以上是在LINUX的做法,那么在WINDOWS里的做法,我从VC知识库看到了一篇文章如下:

在UTF-8,与UNICODE之间转换的时候,用二进制运算,代替了字符串的转换。UTF-8一个汉字,用3个字节,而UNICODE用2个字节;对应关系如下:

UTF-8编码:         
      [1,1,1,0,A5,A6,A7,A8],    [1,0,B3,B4,B5,B6,B7,B8],            
      [1,0,C3,C4,C5,C6,C7,C8];

对应的UNICODE编码:

[A5,A6,A7,A8,B3,B4,B5,B6],         
      [B7,B8,C3,C4,C5,C6,C7,C8]

因此我们只需进行位操作,即可达到目的;如:

      // 把UTF-8转换成Unicode
      void CChineseCodeLib::UTF_8ToUnicode(WCHAR* pOut,char *pText)
      {
     	 char* uchar = (char *)pOut;
     	
     	 uchar[1] = ((pText[0] & 0x0F) << 4) + ((pText[1] >> 2) & 0x0F);
     	 uchar[0] = ((pText[1] & 0x03) << 6) + (pText[2] & 0x3F);
     
     	 return;
      }
     // Unicode 转换成UTF-8 
     void CChineseCodeLib::UnicodeToUTF_8(char* pOut,WCHAR* pText)
     {
	      // 注意 WCHAR高低字的顺序,低字节在前,高字节在后
	      char* pchar = (char *)pText;

	      pOut[0] = (0xE0 | ((pchar[1] & 0xF0) >> 4));
	      pOut[1] = (0x80 | ((pchar[1] & 0x0F) << 2)) + ((pchar[0] & 0xC0) >> 6);
	      pOut[2] = (0x80 | (pchar[0] & 0x3F));
	
	      return;
     }
     
     // 把Unicode 转换成 GB2312 
     void CChineseCodeLib::UnicodeToGB2312(char* pOut,unsigned short uData)
     {
	     WideCharToMultiByte(CP_ACP,NULL,&uData,1,pOut,sizeof(WCHAR),NULL,NULL);
	     return;
     }     
     
     // GB2312 转换成 Unicode
     void CChineseCodeLib::Gb2312ToUnicode(WCHAR* pOut,char *gbBuffer)
     {
	     ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,gbBuffer,2,pOut,1);
	     return;
     }
     
     //GB2312 转为 UTF-8
     void CChineseCodeLib::GB2312ToUTF_8(string& pOut,char *pText, int pLen)
     {
           char buf[4];
           char* rst = new char[pLen + (pLen >> 2) + 2];
           
           memset(buf,0,4);
           memset(rst,0,pLen + (pLen >> 2) + 2);
           
           int i = 0;
           int j = 0;      
           while(i < pLen)
           {
                   //如果是英文直接复制就可以
                   if( *(pText + i) >= 0)
                   {
                           rst[j++] = pText[i++];
                   }
                   else
                   {
                           WCHAR pbuffer;
                           Gb2312ToUnicode(&pbuffer,pText+i);
                           
                           UnicodeToUTF_8(buf,&pbuffer);
                           
                           unsigned short int tmp = 0;
                           tmp = rst[j] = buf[0];
                           tmp = rst[j+1] = buf[1];
                           tmp = rst[j+2] = buf[2];
                           
                           
                           j += 3;
                           i += 2;
                   }
           }
           rst[j] = ''/0'';
   
           //返回结果
           pOut = rst;             
           delete []rst;   
           
           return;
     }
     
     //UTF-8 转为 GB2312
     void CChineseCodeLib::UTF_8ToGB2312(string &pOut, char *pText, int pLen)
     {
         char * newBuf = new char[pLen];
         char Ctemp[4];
         memset(Ctemp,0,4);

         int i =0;
         int j = 0;
         
         while(i < pLen)
         {
                if(pText[i] > 0)
                {
                        newBuf[j++] = pText[i++];                       
                }
                else                 
                {
                        WCHAR Wtemp;
                        UTF_8ToUnicode(&Wtemp,pText + i);
                
                        UnicodeToGB2312(Ctemp,Wtemp);
                    
                        newBuf[j] = Ctemp[0];
                        newBuf[j + 1] = Ctemp[1];

                        i += 3;    
                        j += 2;   
                }
         }
         newBuf[j] = ''/0'';
         
         pOut = newBuf;
         delete []newBuf;
         
         return; 
     }

以上给出的代码可以让我们轻松的实现gb2312和UTF-8之间的转换,我们可以从

http://www.nongnu.org/scew/

http://www.jclark.com/xml/expat.html

找到我们需要的EXPAT XML PARSER.当然,至于它的用法,大家看它的网站上的说明好了.我就不再废话.

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:1854320次
    • 积分:20437
    • 等级:
    • 排名:第403名
    • 原创:141篇
    • 转载:667篇
    • 译文:6篇
    • 评论:368条
    文章存档
    最新评论