2013-03-18 246 views
9

我一直在探索C++ 11的新Unicode功能,雖然other C++11 encoding questions已經非常有幫助,但我對cppreference以下代碼段有疑問。代碼寫入並立即讀取以UTF-8編碼保存的文本文件。在C++中讀寫/打印UTF-8 11

// Write 
std::ofstream("text.txt") << u8"z\u6c34\U0001d10b"; 

// Read 
std::wifstream file1("text.txt"); 
file1.imbue(std::locale("en_US.UTF8")); 
std::cout << "Normal read from file (using default UTF-8/UTF-32 codecvt)\n"; 
for(wchar_t c; file1 >> c;) // ? 
    std::cout << std::hex << std::showbase << c << '\n'; 

是很簡單的,爲什麼是wchar_t需要在for環路我的問題? A u8字符串文字可以使用簡單的char *來聲明,而UTF-8編碼的位佈局應該告訴系統字符的寬度。看起來有一些從UTF-8到UTF-32的自動轉換(因此wchar_t),但如果是這種情況,爲什麼需要轉換?

+0

這取決於很多事情。值得注意的是,正確的UTF8行爲在控制檯應用程序中使用Windows時不是不可能的(如果不是不可能的話)(要求_至少有很多非標準API調用IIRC) – sehe 2013-03-18 10:57:10

+1

使用'wchar_t'是因爲使用了wifstream而wifstream執行你提到的「一些自動轉換」。我的觀點是要展示自動轉換(爲一個特定平臺實現)和'codecvt_utf8_utf16'提供的明確的,可移植的,與區域無關的Unicode轉換之間的區別。 – Cubbi 2013-03-18 14:29:33

回答

5

您使用wchar_t,因爲您使用wifstream來讀取文件;如果您正在使用ifstream進行閱讀,則您將使用char,並且類似地使用char16_tchar32_t

假設(作爲示例執行),該wchar_t是32位,並且所述本地字符集,它代表是UTF-32(UCS-4),那麼這是要讀取的文件作爲最簡單的方法UTF-32;它在這個例子中是這樣表示的,以便將文件讀作UTF-16。更爲便攜的方法是明確使用basic_ifstream<char32_t>std::codecvt_utf8<char32_t>,因爲這可以保證從UTF-8輸入流轉換爲UTF-32元素。

+1

+1,我寫這個例子和對比是我的目標。 – Cubbi 2013-03-18 13:54:02

+0

啊我明白了!因此,總是明確地將UTF-8轉換爲更寬的'wchar_t',或者使用'ifstream'將原始UTF-8字節提取到本地'char'數組中是否可以接受?我不確定是否從@ Cubbi的例子推斷後者是不好的做法,或者它是否超出了範例的範圍。 – Ephemera 2013-03-19 00:47:40

+0

@PLPiper是的,你可以隨時讀取任何多字節編碼文件到char數組中,而無需進行任何轉換。使用標準C++中的這樣的數組沒有太多的功能(除了首先轉換爲寬),但是大量的庫需要使用utf8輸入。 – Cubbi 2013-03-19 02:26:00

2

您使用的cppreference代碼片段的想法是展示如何將UTF-8文件讀取到UTF-16字符串中,這就是爲什麼他們使用ofstream編寫文件,但是使用wifstream讀取文件(因此wchar_t) 。