真正UTF-8与GB2312间的转换(兼容windows和Linux)

                                                       UTF-8与GB2312间的转换
                                                               作者:曾刘彬
中文转码是程序员可能经常遇到的一个问题,鄙人在这方面有些心得,故在此抛砖引玉了。
    我在网上看到好多关于UTF-8与BG2312间互相转换都用一下的方法(为了方便,以后我称之为“拼凑法”):
  // 把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;
  }
    “拼凑法”可以成功的转换大部分的UTF-8编码,不过作为一个负责的人,我想指出其中的缺陷:
    真正的UTF-8的编码规则如下:
 U-00000000 - U-0000007F: 0xxxxxxx   
 U-00000080 - U-000007FF: 110xxxxx 10xxxxxx   
 U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx   
 U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx   
 U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx   
 U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 

        可见UTF-8 编码字符理论上可以是1 - 6 个字节长,而“拼凑法”只处理了1字节和3字节两种编码方式。有的人可能会说:16 位 BMP 字符最多只用到 3 字节长。这没错,拼凑发也没处理2字节编码方式。所以我得出结论:“拼凑法”是不安全的。
        言归正传,其实UTF-8与GB2312之间的转化不用弄得那么复杂。
        在windows下用这两个现成的函数,通过不同的参数就能实现。   
            ::WideCharToMultiByte(。。。)   
            ::MultiByteToWideChar(。。。)
        若在Linux下,则用iconv命令实现。 具体代码如下:
        如果是windows下,则:#define __cdn_win32_platform__
#define CP_GB2312 20936
class CodingTransformer {
public:
 //GB2312 转为 UTF-8
 int  UTF_8ToGB2312(char* pOut, int iBufSize, char *pText, int iLenth);
 //GB2312 转为 UTF-8
 int  GB2312ToUTF_8(char* pOut, int iBufSize,char *pText, int iLenth);
};
int CodingTransformer::UTF_8ToGB2312(char* pOut, int iBufSize, char *pText, int pLen)
{
#ifdef __cdn_win32_platform__
 WCHAR* pWtemp = new WCHAR[pLen];
 int iWcharLenth = ::MultiByteToWideChar(CP_UTF8,0,pText,-1,pWtemp,pLen); 
 if (0 == iWcharLenth)
 {
  DWORD dwLastErr = GetLastError();
  printf("alexaroma:转码错误,错误号:%d/n", dwLastErr);
  delete pWtemp;
  return 0;
 }
 int iMultByteLenth = ::WideCharToMultiByte(CP_GB2312, NULL, pWtemp,
                                         iWcharLenth, pOut,
              iBufSize, NULL, NULL);
 if (0 == iMultByteLenth)
 {
  DWORD dwLastErr = GetLastError();
  printf("alexaroma:转码错误,错误号:%d/n", dwLastErr);
  delete pWtemp;
  return 0;
 }
 delete pWtemp;
 return iMultByteLenth;
#else//__cdn_win32_platform__
 iconv_t cd;
 int rc;
 char   **pin   =   &pText;
 char   **pout   =   &pOut;
 int outlen = iBufSize;
 cd   =   iconv_open("GB2312","UTF-8");
 if(cd==0)return -1;
 memset(pOut,0,strlen(pOut));
 if(iconv(cd,pin,(size_t   *)&pLen,pout,(size_t   *)&outlen) == -1)
 {
  iconv_close(cd);
  return outlen;
 }
 iconv_close(cd);
 return -1;
#endif//__cdn_win32_platform__
}
int  CodingTransformer::GB2312ToUTF_8(char* pOut, int iBufSize,
           char *pText, int pLen)
{
#ifdef __cdn_win32_platform__
 WCHAR* pWtemp = new WCHAR[pLen];
 int iWcharLenth = ::MultiByteToWideChar(CP_GB2312, MB_PRECOMPOSED,
                                      pText, -1, pWtemp, pLen);
 if (0 == iWcharLenth)
 {
  DWORD dwLastErr = GetLastError();
     printf("alexaroma:转码错误,错误号:%d/n", dwLastErr);
  delete pWtemp;  return 0;
 }
 int iMultByteLenth = ::WideCharToMultiByte(CP_UTF8, 0, pWtemp,
                                         iWcharLenth, pOut,
              iBufSize, NULL, NULL);
 if (0 == iMultByteLenth)
 {
  DWORD dwLastErr = GetLastError();
  printf("alexaroma:转码错误,错误号:%d/n", dwLastErr);
  delete pWtemp;
  return 0;
 }
 delete pWtemp;
 return iMultByteLenth;
#else//__cdn_win32_platform__
 iconv_t cd;
 int   rc;
 char   **pin   =   &pText;
 char   **pout   =   &pOut;
 int outlen = iBufSize;
 cd=iconv_open("UTF-8","GB2312");
 if(cd==0)return -1;
 memset(pOut,0,strlen(pOut));
 if(iconv(cd,pin,(size_t   *)&pLen,pout,(size_t   *)&outlen) == -1)
 {
  iconv_close(cd);
  return outlen;
 }
 iconv_close(cd);
 return -1;
#endif//__cdn_win32_platform__
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目中有很多文件因为编码的原因导致用户使用的时候看到的是乱码,或是不兼容的情况,网上找了一圈 也没有适合咱程序员的转码的工具,所以写了一个批量转换工具 虽然已经使用在我司生产项目中,但还是建议你转换前备份一次文件 注意(使用前必看): 注意(使用前必看): 注意(使用前必看): 支持所有文本格式的文档(如 txt,js,css,java,c..),二进制或程序(如word,excel,exe文件)不要使用本转换工具,因为是JAVA程序 需要你的机器上已经安装了JDK 使用方法: 1,打开start.sh文件,windows用户把扩展名.sh修改为.bat 2,修改三个双引号("")中的参数, 第一个参数是文件夹路径, 第二个参数表示要转换成的编码 如utf-8,utf-8-bom,ansi 等编码都支持 第二个参数表示要转换的文件类型,以扩展名的形式提供支持,可以提供多个文件扩展名 以空格分隔 如:我要转换E盘下 E:\work_architecture\doc目录下的所有js 和 css 文件 编码为 utf-8 那么,你要执行的命令就是 java -jar code_conversion.jar "E:\work_architecture\doc" "utf-8" ".js .css" 还是挺简单的吧~~ 支持的功能: 1,批量转换,子目录自动发现 2,文件编码自动识别,所以使用的时候不用提供原文件的编码;识别不了不会转换,保证项目文件的安全 3,支持utf-8-bom编码 4,兼容Linux & Windows & Mac系统 5,不用安装,只要机器有JDK就可以使用 需要源码的请邮件[email protected] 或 私信我

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值