我愛我的家園!

          成功在于你是否努力,希望在于你是否相信自己!

           

          Ansi、Unicode、UTF8字符串之間的轉換和寫入文本文件

          轉載請注明出處http://www.cppblog.com/greatws/archive/2008/08/31/60546.html

          最近有人問我關于這個的問題,就此寫一篇blog

          Ansi字符串我們最熟悉,英文占一個字節(jié),漢字2個字節(jié),以一個\0結尾,常用于txt文本文件
          Unicode字符串,每個字符(漢字、英文字母)都占2個字節(jié),以2個連續(xù)的\0結尾,NT操作系統(tǒng)內核用的是這種字符串,常被定義為typedef unsigned short wchar_t;所以我們有時常會見到什么char*無法轉換為unsigned short*之類的錯誤,其實就是unicode
          UTF8是Unicode一種壓縮形式,英文A在unicode中表示為0x0041,老外覺得這種存儲方式太浪費,因為浪費了50%的空間,于是就把英文壓縮成1個字節(jié),成了utf8編碼,但是漢字在utf8中占3個字節(jié),顯然用做中文不如ansi合算,這就是中國的網頁用作ansi編碼而老外的網頁常用utf8的原因。
          UTF8在還游戲里運用的很廣泛,比如WOW的lua腳本等

          下面來說一下轉換,主要用代碼來說明吧
          寫文件我用了CFile類,其實用FILE*之類的也是一樣,寫文件和字符串什么類別沒有關系,硬件只關心數(shù)據(jù)和長度

          Ansi轉Unicode
          介紹2種方法

          void CConvertDlg::OnBnClickedButtonAnsiToUnicode()
          {
          ???
          // ansi to unicode
          ??? char * szAnsi = ? " abcd1234你我他 " ;
          ???
          // 預轉換,得到所需空間的大小
          ??? int wcsLen = ::MultiByteToWideChar(CP_ACP, NULL, szAnsi, strlen(szAnsi), NULL, 0 );
          ???
          // 分配空間要給'\0'留個空間,MultiByteToWideChar不會給'\0'空間
          ??? wchar_t * wszString = ? new wchar_t[wcsLen + ? 1 ];
          ???
          // 轉換
          ??? ::MultiByteToWideChar(CP_ACP, NULL, szAnsi, strlen(szAnsi), wszString, wcsLen);
          ???
          // 最后加上'\0'
          ??? wszString[wcsLen] = ? ' \0 ' ;
          ???
          // unicode版的MessageBox API
          ??? ::MessageBoxW(GetSafeHwnd(), wszString, wszString, MB_OK);

          ???
          // 接下來寫入文本
          ???
          // 寫文本文件,頭2個字節(jié)0xfeff,低位0xff寫在前
          ??? CFile cFile;
          ??? cFile.Open(_T(
          " 1.txt ") , CFile::modeWrite | CFile::modeCreate);
          ???
          // 文件開頭
          ??? cFile.SeekToBegin();
          ??? cFile.Write(
          " \xff\xfe " , 2 );
          ???
          // 寫入內容
          ??? cFile.Write(wszString, wcsLen * ? sizeof (wchar_t));
          ??? cFile.Flush();
          ??? cFile.Close();
          ??? delete[] wszString;
          ??? wszString
          = NULL;


          ???
          // 方法2
          ???
          // 設置當前地域信息,不設置的話,使用這種方法,中文不會正確顯示
          ???
          // 需要#include<locale.h>
          ??? setlocale(LC_CTYPE, " chs " );
          ??? wchar_t wcsStr[
          100 ];
          ???
          // 注意下面是大寫S,在unicode中,代表后面是ansi字符串
          ???
          // swprintf是sprintf的unicode版本
          ???
          // 格式的前面要加大寫L,代表是unicode
          ??? swprintf(wcsStr, L " %S " , szAnsi);
          ??? ::MessageBoxW(GetSafeHwnd(), wcsStr, wcsStr, MB_OK);

          }



          Unicode轉Ansi
          也是2種方法

          void CConvertDlg::OnBnClickedButtonUnicodeToAnsi()
          {
          ???
          // unicode to ansi
          ??? wchar_t * wszString = L " abcd1234你我他 " ;
          ???
          // 預轉換,得到所需空間的大小,這次用的函數(shù)和上面名字相反
          ??? int ansiLen = ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), NULL, 0 , NULL, NULL);
          ???
          // 同上,分配空間要給'\0'留個空間
          ??? char * szAnsi = ? new ? char [ansiLen + ? 1 ];
          ???
          // 轉換
          ???
          // unicode版對應的strlen是wcslen
          ??? ::WideCharToMultiByte(CP_ACP, NULL, wszString, wcslen(wszString), szAnsi, ansiLen, NULL, NULL);
          ???
          // 最后加上'\0'
          ??? szAnsi[ansiLen] = ? ' \0 ' ;
          ???
          // Ansi版的MessageBox API
          ??? ::MessageBoxA(GetSafeHwnd(), szAnsi, szAnsi, MB_OK);

          ???
          // 接下來寫入文本
          ???
          // 寫文本文件,ANSI文件沒有BOM
          ??? CFile cFile;
          ??? cFile.Open(_T(
          " 1.txt ") , CFile::modeWrite | CFile::modeCreate);
          ???
          // 文件開頭
          ??? cFile.SeekToBegin();
          ???
          // 寫入內容
          ??? cFile.Write(szAnsi, ansiLen * ? sizeof ( char ));
          ??? cFile.Flush();
          ??? cFile.Close();
          ??? delete[] szAnsi;
          ??? szAnsi
          = NULL;


          ???
          // 方法2
          ???
          // 和上面一樣有另一種方法
          ??? setlocale(LC_CTYPE, " chs " );
          ???
          char szStr[ 100 ];
          ???
          // 注意下面是大寫,在ansi中,代表后面是unicode字符串
          ???
          // sprintf
          ??? sprintf(szStr, " %S " , wszString);
          ??? ::MessageBoxA(GetSafeHwnd(), szStr, szStr, MB_OK);
          }



          Unicode轉UTF8

          void CConvertDlg::OnBnClickedButtonUnicodeToU8()
          {
          ???
          // unicode to UTF8
          ??? wchar_t * wszString = L " abcd1234你我他 " ;
          ???
          // 預轉換,得到所需空間的大小,這次用的函數(shù)和上面名字相反
          ??? int u8Len = ::WideCharToMultiByte(CP_UTF8, NULL, wszString, wcslen(wszString), NULL, 0 , NULL, NULL);
          ???
          // 同上,分配空間要給'\0'留個空間
          ???
          // UTF8雖然是Unicode的壓縮形式,但也是多字節(jié)字符串,所以可以以char的形式保存
          ??? char * szU8 = ? new ? char [u8Len + ? 1 ];
          ???
          // 轉換
          ???
          // unicode版對應的strlen是wcslen
          ??? ::WideCharToMultiByte(CP_UTF8, NULL, wszString, wcslen(wszString), szU8, u8Len, NULL, NULL);
          ???
          // 最后加上'\0'
          ??? szU8[u8Len] = ? ' \0 ' ;
          ???
          // MessageBox不支持UTF8,所以只能寫文件

          ???
          // 接下來寫入文本
          ???
          // 寫文本文件,UTF8的BOM是0xbfbbef
          ??? CFile cFile;
          ??? cFile.Open(_T(
          " 1.txt " ), CFile::modeWrite | CFile::modeCreate);
          ???
          // 文件開頭
          ??? cFile.SeekToBegin();
          ???
          // 寫B(tài)OM,同樣低位寫在前
          ??? cFile.Write( " \xef\xbb\xbf " , 3 );
          ???
          // 寫入內容
          ??? cFile.Write(szU8, u8Len * ? sizeof ( char ));
          ??? cFile.Flush();
          ??? cFile.Close();
          ??? delete[] szU8;
          ??? szU8
          = NULL;

          }


          UTF8轉UNICODE

          void CConvertDlg::OnBnClickedButtonU8ToUnicode()
          {
          ???
          // UTF8 to Unicode
          ???
          // 由于中文直接復制過來會成亂碼,編譯器有時會報錯,故采用16進制形式
          ??? char * szU8 = ? " abcd1234\xe4\xbd\xa0\xe6\x88\x91\xe4\xbb\x96\x00 " ;
          ???
          // 預轉換,得到所需空間的大小
          ??? int wcsLen = ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), NULL, 0 );
          ???
          // 分配空間要給'\0'留個空間,MultiByteToWideChar不會給'\0'空間
          ??? wchar_t * wszString = ? new wchar_t[wcsLen + ? 1 ];
          ???
          // 轉換
          ??? ::MultiByteToWideChar(CP_UTF8, NULL, szU8, strlen(szU8), wszString, wcsLen);
          ???
          // 最后加上'\0'
          ??? wszString[wcsLen] = ? ' \0 ' ;
          ???
          // unicode版的MessageBox API
          ??? ::MessageBoxW(GetSafeHwnd(), wszString, wszString, MB_OK);

          ???
          // 寫文本同ansi to unicode
          }



          Ansi轉換utf8和utf8轉換Ansi就是上面2個的結合,把unicode作為中間量,進行2次轉換即可

          by greatws

          posted on 2008-09-16 17:59 死神 閱讀(955) 評論(0)  編輯  收藏 所屬分類: C/C++

          導航

          統(tǒng)計

          公告

          歡迎大家來到我的個人世界!

          常用鏈接

          留言簿(3)

          隨筆分類(5)

          隨筆檔案(9)

          文章分類(37)

          文章檔案(41)

          相冊

          語音技術

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 股票| 迁西县| 丹东市| 根河市| 鄄城县| 昭觉县| 汉源县| 宣恩县| 淳安县| 沈阳市| 岳普湖县| 左贡县| 隆安县| 云霄县| 阿荣旗| 鲜城| 大方县| 天台县| 平利县| 嵊泗县| 房山区| 黑河市| 龙川县| 双流县| 隆化县| 广德县| 开封市| 东莞市| 江安县| 日土县| 柞水县| 旬阳县| 康乐县| 丁青县| 米脂县| 大冶市| 泰顺县| 吉林省| 景洪市| 德保县| 晋中市|