字符集研究之不同字符集的轉換方式


作者:朱金燦

來源:http://blog.csdn.net/clever101

 

        在上篇文章中介紹了多字節字符集和unicode字符集,今天介紹下兩大字符集之間的轉換方式。

 

       首先談談的是微軟對於unicode字符集的態度。在windows的開發體系下,unicode字符字符集被稱為寬字節字符集,多字節字符集被稱為窄字符集。微軟對unicode字符集是大力支持的。從以下幾點可以看出:從windows2000開始使用unicode進行開發;Windows CE 本身就是使用Unicode的一種操作系統,完全不支持ANSI版Windows API函數;新建的VC工程默認使用的是unicode字符集(utf16)。那么問題來了,作為一個C++程序員,是否該使用unicode字符集。

 

       為什么使用Unicode字符集?提升運行效率,比如Windows內核本身是基於unicode字符的,非unicode字符傳進入要先轉成unicode字符(《windows核心編程有詳細解釋》);在不同語言中可以方便交換數據,比如在英文版操作系統中輸入中文路徑,如果是非unicode字符同時又沒有安裝中文字符集,那么就會出現亂碼。

 

         為什么不使用Unicode字符集?因為傳統的勢力很強大,很多跨平台的第三方庫都是基於多字節字節集進行開發,還有就是編程習慣,比如在Windows下開發,大家耳熟能詳的是計算字符串長度的函數是strlen,誰會去用寬字節版的wcslen呢。詳見我以前寫的文章:

unicode字符集,用還是不用?

 

       最后談談多字節字符集和unicode字符集。兩種方式,一種是使用跨平台的iconv庫,示例代碼如下:

include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;

#include <iconv.h> //編碼轉換庫

#define OUTLEN 255 //文件路徑長度

//代碼轉換:從一種編碼轉為另一種編碼
int code_convert(char *from_charset, char *to_charset, char *inbuf, size_t inlen, char *outbuf, size_t outlen)
{
iconv_t cd;
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, size_t inlen, char *outbuf, size_t 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);
}

//執行SQL語句回調函數
static int _sql_callback(void* pUsed, int argc, char** argv, char** ppszColName)
{
for(int i=0; i<argc; i++)
{
printf("%s = %s/n", ppszColName[i], argv[i]==0 ? "NULL" : argv[i]);
}
return 0;
}

void main()
{
char *in_gb2312 = "D://控制點庫//GCPDB.3sdb";

char out[OUTLEN];

//gb2312碼轉為unicode碼
g2u(in_gb2312,strlen(in_gb2312),out,OUTLEN);
printf("gb2312-->unicode out=%s /n",out);
}

另一種方式是使用使用WindiwsAPI,示例代碼如下:

std::string MbcsToUtf8( const char* pszMbcs )      {          std::string str;          WCHAR   *pwchar=0;          CHAR    *pchar=0;          int len=0;          int codepage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;          len=MultiByteToWideChar(codepage, 0, pszMbcs, -1, NULL,0);          pwchar=new WCHAR[len];          if(pwchar!=0)          {              len = MultiByteToWideChar(codepage, 0, pszMbcs, -1, pwchar, len);              if( len!=0 )              {                  len = WideCharToMultiByte(CP_UTF8, 0, pwchar, -1, 0, 0, 0, 0);                  pchar=new CHAR[len];                  if(pchar!=0)                  {                      len = WideCharToMultiByte(CP_UTF8, 0, pwchar, -1, pchar, len,0, 0);                      if(len!=0)                                      {                          str = pchar;                                         }                      delete pchar;                  }                  delete pwchar;              }          }          return str;  }  

參考文獻:

 

1. 使用SQLite3支持中文路徑


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com