簡體   English   中英

如何使用C ++ 11語言環境設施將UTF-8用作字符串的內部表示?

[英]How to use C++11 locale facilities to use UTF-8 as internal representation of strings?

我正在編寫一個處理文件和目錄的可移植庫。 我想使用UTF-8作為輸入(目錄路徑)和輸出(文件路徑)。 問題是,Windows讓我可以選擇使用UTF-16-UCS-2和代碼頁。 所以我必須將我的所有UTF-8字符串轉換為UTF-16,將它們傳遞給WinAPI,然后將結果轉換回UTF-8。 C ++ 11似乎只提供了<locale>庫,除了我所理解的,沒有任何預定義的特化使用UTF-8作為內部(即我的側面)編碼 - 最接近的是UTF-16- to-UTF-8,這我想要的完全相反 所以這是第一個問題:

1)如何使用codecvt thingamajigs將我的UTF-8字符串轉換為UTF-16進行WinAPI調用,UTF-16結果返回UTF-8?

另一個問題:我也在瞄准Linux。 在Linux上,對許多不同的語言環境有很好的支持 - 我不希望有任何不同。 希望每個人都在他們的Linux機器上使用UTF-8,但沒有嚴格的保證。 所以我認為擴展上面特定於Windows的行為並始終執行UTF-8到系統區域設置編碼是一個好主意。 除了我沒有看到C ++ 11的<locale>庫中有任何方法可以獲得當前的系統編碼! 默認的std :: locale構造函數使用自己定義的語言環境,如果不這樣做,它將返回經典的“C”語言環境。 並且沒有其他我知道的吸氣劑。 所以這是第二個問題:

2)如何檢測當前系統區域設置? <locale>有什么東西? 也許一些標准的C庫函數,或者(在這種情況下可移動性較差)POSIX API中的東西?

標准庫中這些工具的設計假定多字節字符編碼(如UTF-8)僅用於外部存儲(即磁盤上文件中的字節序列),並且內存中的所有字符大小均勻。 這就像std::basic_string<T>::operator[]這樣的行為可以與標准強加的性能約束一致。 因此,雖然您可以使用以UTF-8或其他MBCS編碼的文件(如日語),但內存中的字符串應為charchar16_tchar32_twchar_t

這就是為什么你沒有在標准庫中找到你想要做什么的原因,因為內存中的字符串不打算以UTF-8存儲。 這類似於其他語言,例如Java,其中磁盤上的數據被解釋為字節流並將它們轉換為字符串,您需要告訴某個組件字節流的預期字符編碼。 某些操作系統可能會將UTF-8字符串填入argv[] ,但這是非標准的。 這就是為什么Windows上WinMain的Unicode啟用入口點提供了一個NUL終止指向wchar_t指針,而不是指向UTF-8編碼字符串的char*

IBM的Unicode國際組件庫提供了一整套與C ++標准庫互補和設計的組件。 我會看看他們的代碼轉換工具。 雖然標准在<locale>定義了用於代碼轉換的工具,但它不保證存在從UTF-8映射到char16_tchar32_twchar_t的代碼轉換工具。 如果存在這樣的事情,您只能根據實施細節獲得。 ICU庫為任何C ++實現提供了可移植的功能。 這是很好的支持和良好使用,並不太可能有錯誤的UTF-8字符串解碼成相應的更寬於─ char的字符串。

康拉德在評論中提到了UTF-8 Anywhere Manifesto。 這是一個有趣的閱讀,它們指向Boost.Nowide庫(尚未正式成為提升的一部分),以獲得您在上面提到的問題的解決方案。

請注意,我的答案只是描述現有C ++標准庫類(如std::basic_string<T>工作方式。 它不是針對UTF-8,Unicode或其他任何內容的建議。 引用的宣言同意我的觀點,即這些東西根本無法以這種方式工作,如果你想在任何地方使用UTF-8,那么你需要別的東西。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM