2012-06-25 17 views
3

我必須在Windows的MSVC 10中使用Unicode UTF-8的應用程序中編寫代碼。我知道UTF-8編碼的字符串將使用每個字符1或2個字節。所以,我的問題是:std :: string是否適合這個?如果是的話,我該如何解碼字符串?據我所知std :: string只是一個字節數組,它不提供任何解碼邏輯。 我怎樣才能知道字符串的邏輯長度?我如何從字符串中提取邏輯字符?是否有任何庫可以幫助我從字符串中提取邏輯字符?UTF-8解碼庫

例如:如果我有性病字符串「奧萊報」 :: string的,我需要知道的是,長度爲3,而不是4.

+6

UTF-8每個字符最多可以使用4個字節,而不只是一個或兩個。 – deceze

+1

通過解碼字符串,你的意思是什麼[確切地說](http://utf8everywhere.org/#faq.glossary)?更重要的是,爲什麼你需要知道長度? Unicode通常沒有意義。 – ybungalobill

回答

-2

首先,你可能需要調用mbstowcs()函數將UTF-8字符轉換爲寬字符。然後,如果您希望結果爲8位,那麼如果您有「Unicode」字符(ISO-8859-1平面以外的字符,也稱爲Latin 1),則會丟失數據。

請注意,「Windows」編碼不等於ISO-8859-1的1到1,但在大多數情況下,ISO-8859-1是人們現在使用的。

參考:http://www.cplusplus.com/reference/clibrary/cstdlib/mbstowcs/

好吧,如果你只是想字符長度,使用mblen()函數:

len = mblen(str.c_str(), str.length()); 

附加說明:一個簡單的方法來實現mblen()是計數不在0x80和0xBF之間的字節數,因爲它們是多字節序列的一部分。如果您通過片狀串行連接接收到UTF-8字節序列,這一點特別有用。

+0

「在大多數情況下,ISO-8859-1是人們現在使用的東西」。在interwebs上,我發現CP1252相當頻繁地被貼上了ISO-8859-1的標籤。不確定哪一個你會說他們在這種情況下「使用」,但是「大多數人」使用的都不重要,重要的是少數人的文本打破了你的代碼;-) –

+0

這就是不是OP想要的。他爲什麼要將UTF-16無損地轉換爲單字節碼點?這個問題並不意味着在任何地方。提到ISO-8859-1只是被誤導了。 「在大多數情況下[這是]人們現在使用的東西」是完全錯誤的。事實上,現代瀏覽器實際上使用不同的編碼*,即使你明確地要求這種編碼,因爲即使他們這樣說,幾乎沒有人會表示ISO-8859-1。 –

+0

或者如何轉換爲utf-16或utf-32進行內部處理。 –

2

是,std::string是appropriare但你已經注意到了這一點只在字節,而不是Unicode代碼點進行操作。那std::string是不透明的類型;這並不一定是壞的(事實上,它有一些優點,請參閱下面的鏈接以獲取信息),但是如果需要有關字符的信息,則需要對字符串進行解碼。

對於UTF-8的實際處理(如有必要),可以使用Boost.NoWide庫來解碼UTF-8。

此外,我建議閱讀UTF-8 everywhere manifesto瞭解有關使用UTF-8與其他Unicode轉換的一些信息。

+0

std :: string使得很難通過各種方式對字符串進行排序和測試字符。不,如果你不需要這樣的話,那確實可以使用使用std :: string的UTF-8字符串。你也可以使用QString(Qt)或CString(MFC ...)。 –

+0

感謝@Konrad Rudolph提供鏈接。它們很有用......從最初的一瞥來看,它看起來像Boost.Nowide庫沒有stringstream ...但是,我需要詳細查看。 – PermanentGuest

+1

@Alexis爲此您可以(確實,*必須*)提供自定義比較器。不過,它並不侷限於'std :: string',在使用寬字符時,由於存在組合字符等原因,它甚至是真的。 –