用C++讀寫unicode文本

來源:互聯網
上載者:User

用C++讀寫unicode文本

<致敬原作者>http://librawill.blogspot.com/2008/08/cunicode_2881.html

熟悉一下字元類型,char, wchar_t, TCHAR,最熟悉的char是單位元組字元,適用於ANSI編碼;wchar_t

是雙位元組的寬字元類型,適用於unicode編碼;TCHAR是一個宏,在ANSI壞境下定義為char,unicode

壞境下定義為wchar_t。

怎麼來表示字串?對,字元數組,要知道在C++語言裡面,其實沒有數組的資料結構,所謂數組,都

是由指標+長度來表示。字元型指標const char *, const wchar_t *, const TCHAR *可以用來在不同的環

境下表示字串。再說相關的幾個宏,LPSTR: long point string, 相當於char *; LPCSTR: long point

const string, 相當於 const char *; LPCWSTR: long point const wide string, 相當於 const wchar_t *;

LPCTSTR: 類似的,相當於 const TCHAR *; 這些都不要死記硬背,記著大寫字母的意思即可猜出其含義

一個字串,比如說"北京2008",對應ANSI編碼錶示為 const char * cha = "北京2008"; unicode編碼

表示為 const wchar_t * wcha = L"北京2008"; 。在記憶體裡以二進位儲存,ANSI編碼對應為 0x B1B1

BEA9 32 30 30 38,unicode編碼為 0x 1753 AC4E 3200 3000 3000 3800。

回到上面,為什麼字元型指標可以表示一個字串?電腦找到這個指標,只能知道串首字元,這裡因

為字串有個預設的結束符'\0'(ANSI或者ASCII表示為0x00),從首字元開始,電腦開始向後尋找直

到0x00,認為字串結束,所以儲存字串的時候,電腦是帶著一個特殊結束符的。可是要注意了,

這個結束符0x00是ASCII碼定義的結束符啊,那麼在寬字元unicode環境下呢?結束符是什嗎?是

0x0000。

而對於非const字串,怎麼表示?char * 方法怎麼動態定義長度?好辦,可以用new手動分配記憶體空間

,除此之外,還有更好辦的方法,那就是字串類型string, 怎麼可變長度,怎麼記錄長度,記憶體怎麼存

儲,這些都不用管,都有C++標準庫自動管理。

不同類型的字串間之間怎麼轉換?比如定義 char * cha; string str; str = cha; // 可以實現 char * 到

string 的轉換, cha = str.c_str(); 可以從 string 轉換到 char *;對於wchar_t wcha; wstring wstr; 呢

?wstr = wcha; wcha = wstr.c_str(); // 這個是否可以呢?!

說過了字串的表示和類型轉換,再來看字元流I/O,C++裡面的fstream, ifstream, ofstream, 檔案流

的I/O有好多種方式,預設為字元流方式,明確的說是ANSI字元流,都是針對ANSI文本的,那麼

unicode怎麼讀寫呢?

C++裡倒真有wfsteam流的,可惜用起來也很奇怪,用wifstream讀取unicode文本,結果竟然是讀取一

個位元組,加上一個0x00,在讀取下一個位元組,如此!比如文本裡儲存的還是“北京2008”,剛才說過

unicode編碼為 0x 1753 AC4E 3200 3000 3000 3800;用wifstream讀到記憶體的字元竟是 0x 1700

5300 AC00 4E00 ... 這叫什麼unicode?我不知道wfstream怎麼正確使用用,有知道的朋友還請不吝告

知!

既然wftream不行,那麼怎麼讀取unicode呢,這裡可以借鑒一下二進位流的讀寫方式,二進位流在讀寫

時必須明白儲存單位的資料結構,定義為結構體,然後逐n位元組(n為結構長度)按二進位讀取;這個可

以借鑒過來,不用定義結構了,直接用wchar_t,代碼如下:
ifstream fin;
fin.open(filename, ios::binary);
// 跳過unicode文本開頭有兩個位元組0xFFFE(稱作BOM,用於標識unicode編碼)
fin.seek(2, ios::beg);
while (!fin.eof())
{
wchar_t wch;
fin.read((char *)(&wch), 2);
}

如果要按行讀取,怎麼辦?好了,有ifstream的成員函數getline(cha, size),還有string類成員函數

getline(fin, str)。你試試能不能用在unicode下使用?答案是否定的!為什嗎?因為getline函數預設在

ANSI下使用,它對分行符號的判斷是基於ASCII碼的換行(0x0D)和行開頭標記(0x0A),如果把它用在

unicode編碼下,比如“不”字,unicode編碼為0x0D4E。當getline函數執行到這,以為換行了,所以

說會失效!那麼unicode分行符號以及行開頭符的二進位是什嗎?雙位元組了,是0x0D00和0x0A00,這時候

getline函數就失效了,怎麼辦,手動判斷:
ifstream fin;
fin.open(filename, ios::binary);
size_t index = 2;
while (!fin.eof())
{
fin.seekg(index, ios::beg);
wchar_t wch;
fin.read((char *)(&wch), 2);
if (wch == 0x000D) // 判斷斷行符號
{
strLineAnsi = ws2s(wstrLine);
wstrLine.erase(0, wstrLine.size() + 1);
iLine++;
index += 4; // 跳過斷行符號符和行開頭符
}
else
{
wstrLine.append(1, wch);
index += 2;
}
}

上面的程式可以讀取unicode了,那麼讀了進來怎麼理解unicode呢,這就需要char * 和 wchar_t *間的

轉換了,這個沒有簡便的方法,ANSI、UNICODE兩種編碼之間的轉換,只能靠查表實現,C++提供了

兩個函數,wcstombs(_Dest, _Source, _Dsize) 從unicode編碼轉化為ANSI編碼 ,mbstowcs(_Dest,

_Source, _Dsize)反之,參數對應為const char*, const wchar_t*以及長度。這裡在提供一個網上的函數

,用於實現string和wstring的轉換:
std::string ws2s(const std::wstring& ws)
{
std::string curLocale = setlocale(LC_ALL, NULL); // curLocale = "C";
setlocale(LC_ALL, "chs");
const wchar_t* _Source = ws.c_str();
size_t _Dsize = 2 * ws.size() + 1;
char *_Dest = new char[_Dsize];
memset(_Dest,0,_Dsize);
wcstombs(_Dest,_Source,_Dsize);
std::string result = _Dest;
delete []_Dest;
setlocale(LC_ALL, curLocale.c_str());
return result;
}

std::wstring s2ws(const std::string& s)
{
setlocale(LC_ALL, "chs");
const char* _Source = s.c_str();
size_t _Dsize = s.size() + 1;
wchar_t *_Dest = new wchar_t[_Dsize];
wmemset(_Dest, 0, _Dsize);
mbstowcs(_Dest,_Source,_Dsize);
std::wstring result = _Dest;
delete []_Dest;
setlocale(LC_ALL, "C");
return result;
}

寫到這裡,就可以用C++讀取unicode文本了,寫的方法類似。

本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/jtujtujtu/archive/2009/03/31/4039034.aspx

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.