2013-03-18 18 views
9

Ich habe die neue Unicode-Funktionalität von C++ 11 untersucht, und während other C++11 encoding questions sehr hilfreich waren, habe ich eine Frage zu dem folgenden Code-Snippet von . Der Code schreibt und liest sofort eine Textdatei, die mit der UTF-8-Codierung gespeichert wurde.Lesen/Schreiben/Drucken UTF-8 in C++ 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'; 

Meine Frage ganz einfach ist, warum ist ein wchar_t in der for Schleife benötigt? Ein u8 String-Literal kann mit einem einfachen char * deklariert werden und das Bit-Layout der UTF-8-Codierung sollte dem System die Zeichenbreite mitteilen. Es scheint, es gibt eine automatische Konvertierung von UTF-8 zu UTF-32 (daher die wchar_t), aber wenn dies der Fall ist, warum ist die Konvertierung notwendig?

+0

Es hängt von vielen Dingen ab. Bemerkenswertes, korrektes UTF8-Verhalten ist extrem hart, wenn nicht unmöglich, unter Verwendung von Windows in einer Konsolenanwendung (erfordert mindestens eine große Anzahl von Nicht-Standard-API-Aufrufen IIRC) – sehe

+1

'wchar_t' wird verwendet, weil' wifstream' verwendet wird und 'wifstream' ausführt dass "einige automatische Konvertierung" Sie erwähnen. Mein Punkt war, den Unterschied zwischen dieser automatischen Konvertierung (wie für eine bestimmte Plattform implementiert) und der expliziten, portablen, länderunabhängigen Unicode-Konvertierung, die von 'codecvt_utf8_utf16' bereitgestellt wird, zu zeigen. – Cubbi

Antwort

5

Sie verwenden wchar_t, weil Sie die Datei mit wifstream lesen; Wenn Sie mit ifstream lesen würden, würden Sie char und ähnlich für char16_t und verwenden.

Angenommen (wie das Beispiel der Fall ist), dass wchar_t ist 32-bit, und dass die native Zeichensatz, den sie repräsentiert ist UTF-32 (UCS-4), dann ist dies die einfachste Möglichkeit, eine Datei zu lesen, wie UTF-32; Im Beispiel wird dies als Kontrast zum Lesen einer Datei als UTF-16 dargestellt. Eine portablere Methode wäre, explizit basic_ifstream<char32_t> und std::codecvt_utf8<char32_t> zu verwenden, da dies garantiert von einem UTF-8-Eingangsstrom in UTF-32-Elemente konvertiert wird.

+1

+1, schrieb ich dieses Beispiel und Kontrast war was ich wollte. – Cubbi

+0

Ah ich sehe! Ist es daher besser, UTF-8 immer explizit in ein breiteres 'wchar_t' zu konvertieren, oder ist es noch akzeptabel, die rohen UTF-8-Bytes mit einem' ifstream' in ein natives 'char'-Array zu extrahieren? Ich bin mir nicht sicher, ob ich aus dem Beispiel von Cubbi folgern kann, dass letzteres eine schlechte Übung ist oder ob es nur außerhalb des Anwendungsbereichs des Beispiels liegt. – Ephemera

+0

@PLPiper Ja, Sie können immer lesen, welche Multibyte-Kodierung die Datei in ein Char-Array hat, ohne irgendeine der Konvertierungen vorzunehmen. Es gibt nicht viel, was mit einem solchen Array in Standard-C++ getan werden kann (anders als zuerst in Wide zu konvertieren), aber viele Bibliotheken nehmen utf8-Eingaben vor. – Cubbi

2

Die Idee des cppreference Codeausschnitts, den Sie verwendet haben, ist zu zeigen, wie man eine UTF-8-Datei in eine UTF-16-Zeichenfolge liest. Deshalb schreiben sie die Datei mit einem ofstream, lesen sie aber mit einem wifstream (daher wchar_t) .