2013-03-18 34 views
9

Ho esplorato la nuova funzionalità Unicode di C++ 11 e mentre other C++11 encoding questions sono stato molto utile, ho una domanda sul seguente frammento di codice da cppreference. Il codice scrive e legge immediatamente un file di testo salvato con la codifica UTF-8.Lettura/scrittura/stampa 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'; 

La mia domanda è molto semplicemente, perché è un wchar_t necessaria nel ciclo for? Una stringa letterale u8 può essere dichiarata utilizzando un semplice char * e il layout di bit della codifica UTF-8 dovrebbe indicare al sistema la larghezza del carattere. Sembra che ci sia una conversione automatica da UTF-8 a UTF-32 (da cui il wchar_t), ma se questo è il caso, perché è necessaria la conversione?

+0

Dipende da molte cose. Notevole, il comportamento corretto di UTF8 è estremamente difficile se non impossibile utilizzando Windows in un'applicazione console (che richiede _almeno_ un buon numero di chiamate API non standard IIRC) – sehe

+1

'wchar_t' è usato perché' wifstream' è usato, e 'wifstream' esegue che "qualche conversione automatica" menziona. Il mio punto era mostrare la differenza tra quella conversione automatica (come implementata per una piattaforma particolare) e la conversione Unicode, portatile, indipendente dalla locale, fornita da 'codecvt_utf8_utf16'. – Cubbi

risposta

5

Si utilizza wchar_t perché si sta leggendo il file utilizzando wifstream; se stai leggendo utilizzando ifstream devi utilizzare char e allo stesso modo per char16_t e char32_t.

Assumendo (come l'esempio fa) che wchar_t è a 32 bit, e che il personaggio nativo set che rappresenta è UTF-32 (UCS-4), allora questo è il modo più semplice per leggere un file come UTF-32; è presentato come tale nell'esempio per contrasto alla lettura di un file come UTF-16. Un metodo più portatile sarebbe utilizzare esplicitamente basic_ifstream<char32_t> e std::codecvt_utf8<char32_t>, poiché è garantito convertire da un flusso di input UTF-8 a elementi UTF-32.

+1

+1, ho scritto quell'esempio e il contrasto era quello che stavo cercando. – Cubbi

+0

Ah, vedo! Quindi è meglio fare sempre una conversione esplicita di UTF-8 in un più ampio 'wchar_t' o è ancora accettabile semplicemente estrarre i byte UTF-8 grezzi in un array' char' nativo usando un 'ifstream'? Non sono sicuro se dedurre dall'esempio @ Cubbi che quest'ultimo è una cattiva pratica, o se è appena al di fuori dello scopo dell'esempio. – Ephemera

+0

@PLPiper si si può sempre leggere qualsiasi codifica multibyte del file in un array di caratteri, senza impegnare nessuna delle conversioni. Non c'è molto che possa essere fatto con tale array all'interno del C++ standard (oltre alla conversione prima in wide), ma molte librerie prendono utf8 input. – Cubbi

2

L'idea dello snippet di codice cppreference che hai usato è di mostrare come leggere un file UTF-8 in una stringa UTF-16, ecco perché scrivono il file usando un ofstream ma lo leggono usando un wifstream (da qui il wchar_t) .