我愛我的家園!

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

           

          Ansi、Unicode、UTF8字符串之間的轉(zhuǎn)換和寫入文本文件

          轉(zhuǎn)載請(qǐng)注明出處http://www.cppblog.com/greatws/archive/2008/08/31/60546.html

          最近有人問我關(guān)于這個(gè)的問題,就此寫一篇blog

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

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

          Ansi轉(zhuǎn)Unicode
          介紹2種方法


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

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


          ????
          // 方法2
          ????
          // 設(shè)置當(dāng)前地域信息,不設(shè)置的話,使用這種方法,中文不會(huì)正確顯示
          ????
          // 需要#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轉(zhuǎn)Ansi
          也是2種方法

          void?CConvertDlg::OnBnClickedButtonUnicodeToAnsi()
          {
          ????
          //?unicode?to?ansi
          ????wchar_t*?wszString?=?L"abcd1234你我他";
          ????
          //預(yù)轉(zhuǎn)換,得到所需空間的大小,這次用的函數(shù)和上面名字相反
          ????int?ansiLen?=?::WideCharToMultiByte(CP_ACP,?NULL,?wszString,?wcslen(wszString),?NULL,?0,?NULL,?NULL);
          ????
          //同上,分配空間要給'\0'留個(gè)空間
          ????char*?szAnsi?=?new?char[ansiLen?+?1];
          ????
          //轉(zhuǎn)換
          ????
          //unicode版對(duì)應(yīng)的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();
          ????
          //寫入內(nèi)容
          ????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轉(zhuǎn)UTF8

          void?CConvertDlg::OnBnClickedButtonUnicodeToU8()
          {
          ????
          //?unicode?to?UTF8
          ????wchar_t*?wszString?=?L"abcd1234你我他";
          ????
          //預(yù)轉(zhuǎn)換,得到所需空間的大小,這次用的函數(shù)和上面名字相反
          ????int?u8Len?=?::WideCharToMultiByte(CP_UTF8,?NULL,?wszString,?wcslen(wszString),?NULL,?0,?NULL,?NULL);
          ????
          //同上,分配空間要給'\0'留個(gè)空間
          ????
          //UTF8雖然是Unicode的壓縮形式,但也是多字節(jié)字符串,所以可以以char的形式保存
          ????char*?szU8?=?new?char[u8Len?+?1];
          ????
          //轉(zhuǎn)換
          ????
          //unicode版對(duì)應(yīng)的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);
          ????
          //寫入內(nèi)容
          ????cFile.Write(szU8,?u8Len?*?sizeof(char));
          ????cFile.Flush();
          ????cFile.Close();
          ????delete[]?szU8;
          ????szU8?
          =NULL;

          }

          UTF8轉(zhuǎn)UNICODE

          void?CConvertDlg::OnBnClickedButtonU8ToUnicode()
          {
          ????
          //UTF8?to?Unicode
          ????
          //由于中文直接復(fù)制過來會(huì)成亂碼,編譯器有時(shí)會(huì)報(bào)錯(cuò),故采用16進(jìn)制形式
          ????char*?szU8?=?"abcd1234\xe4\xbd\xa0\xe6\x88\x91\xe4\xbb\x96\x00";
          ????
          //預(yù)轉(zhuǎn)換,得到所需空間的大小
          ????int?wcsLen?=?::MultiByteToWideChar(CP_UTF8,?NULL,?szU8,?strlen(szU8),?NULL,?0);
          ????
          //分配空間要給'\0'留個(gè)空間,MultiByteToWideChar不會(huì)給'\0'空間
          ????wchar_t*?wszString?=?new?wchar_t[wcsLen?+?1];
          ????
          //轉(zhuǎn)換
          ????::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轉(zhuǎn)換utf8和utf8轉(zhuǎn)換Ansi就是上面2個(gè)的結(jié)合,把unicode作為中間量,進(jìn)行2次轉(zhuǎn)換即可

          by greatws

          posted on 2008-09-04 17:12 死神 閱讀(10081) 評(píng)論(0)  編輯  收藏 所屬分類: Windows編程

          導(dǎo)航

          統(tǒng)計(jì)

          公告

          歡迎大家來到我的個(gè)人世界!

          常用鏈接

          留言簿(3)

          隨筆分類(5)

          隨筆檔案(9)

          文章分類(37)

          文章檔案(41)

          相冊(cè)

          語音技術(shù)

          最新隨筆

          搜索

          積分與排名

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 太谷县| 彭山县| 江安县| 嘉兴市| 常宁市| 北碚区| 二连浩特市| 自贡市| 内乡县| 南丰县| 历史| 岑巩县| 缙云县| 洪洞县| 边坝县| 固镇县| 麻江县| 安泽县| 元阳县| 外汇| 平果县| 西宁市| 苏尼特右旗| 姚安县| 武邑县| 武乡县| 吉安县| 宁远县| 崇州市| 怀集县| 丽江市| 万宁市| 榕江县| 揭东县| 青州市| 溧阳市| 兰溪市| 土默特左旗| 长丰县| 陵水| 古田县|