2012-04-05 14 views
6

Sto programmando (solo occasionalmente) in C++ con VisualStudio e MFC. Scrivo un file con fopen e fprintf. Il file dovrebbe essere codificato in UTF8. C'è qualche possibilità di farlo? Qualunque cosa provi, il file è o un byte doppio unicode o ISO-8859-2 (latin2) codificato.Come scrivere il file UTF-8 con fprintf in C++

Glanebridge

+1

Vedi gli altri post su Unicode in C++ http://stackoverflow.com/questions/55641/unicode-in-c – Dave

+0

Si può provare a vedere questa discussione [entra descrizione Link qui] [1] [1]: http://stackoverflow.com/questions/2543346/how-to-write-unicode-hello-world-in-c-on-windows – Jepessen

risposta

1

In teoria, si dovrebbe semplicemente impostare una localizzazione che utilizza UTF-8 come codifica esterna. La mia comprensione - io non sono un programmatore di Windows - è quella Windows has no such locale, quindi devi ricorrere a mezzi specifici di implementazione o non standard libraries (link dal commento di Dave).

2

Sì, ma è necessario Visual Studio 2005 o versione successiva. È quindi possibile chiamare fopen con i parametri:

LPCTSTR strText = "абв"; 
FILE *f = fopen(pszFilePath, "w,ccs=UTF-8"); 
_ftprintf(f, _T("%s"), (LPCTSTR) strText); 

tenere a mente questo è l'estensione di Microsoft, probabilmente non funzionerà con gcc o altri compilatori.

+0

I don Penso che ciò influirà sui dati scritti nel file usando fprintf. – bames53

+0

È necessario utilizzare _ftprintf. Vedi i cambiamenti nella mia risposta. – sashoalm

+0

O semplicemente usa fwprintf. Quello che sta succedendo è che 'ccs = UTF-8' imposta la modalità _O_U8TEXT sul file, in modo che la scrittura di caratteri ampi nel file causerà l'output di UTF-8. La scrittura di caratteri stretti con questo set di modalità causerà un errore. – bames53

2

Non è necessario impostare le impostazioni internazionali o impostare le modalità speciali sul file se si desidera utilizzare fprintf. Devi semplicemente usare le stringhe codificate UTF-8.

#include <cstdio> 
#include <codecvt> 

int main() { 
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> convert; 
    std::string utf8_string = convert.to_bytes(L"кошка 日本国"); 

    if(FILE *f = fopen("tmp","w")) 
     fprintf(f,"%s\n",utf8_string.c_str()); 
} 

Salvare il programma come UTF-8 con la firma o UTF-16 (vale a dire non usano UTF-8 senza la firma, altrimenti VS non produrrà la stringa destra letterale). Il file scritto dal programma conterrà la versione UTF-8 di quella stringa. Oppure si può fare:

int main() { 
    if(FILE *f = fopen("tmp","w")) 
     fprintf(f,"%s\n","кошка 日本国"); 
} 

In questo caso è necessario salvare il file come UTF-8 senza firma, perché si vuole il compilatore di pensare la codifica sorgente è la stessa della codifica di esecuzione ... Questo è un po 'un hack che si basa sul comportamento del compilatore, IMO, rotto.

È possibile fare praticamente la stessa cosa con qualsiasi altra API per scrivere caratteri stretti in un file, ma si noti che nessuno di questi metodi funziona per scrivere UTF-8 sulla console di Windows. Poiché il runtime C e/o la console sono un po 'rotti, è possibile scrivere UTF-8 direttamente sulla console eseguendo SetConsoleOutputCP (65001) e quindi utilizzando una delle varietà di funzioni puts.

Se si desidera utilizzare caratteri larghi anziché caratteri stretti, i metodi basati sulle impostazioni locali e le modalità di impostazione sui descrittori di file potrebbero entrare in gioco.

#include <cstdio> 
#include <fcntl.h> 
#include <io.h> 

int main() { 
    if(FILE *f = fopen("tmp","w")) { 
     _setmode(_fileno(f), _O_U8TEXT); 
     fwprintf(f,L"%s\n",L"кошка 日本国"); 
    } 
} 

#include <fstream> 
#include <codecvt> 

int main() { 
    if(auto f = std::wofstream("tmp")) { 
     f.imbue(std::locale(std::locale(), 
       new std::codecvt_utf8_utf16<wchar_t>)); // assumes wchar_t is UTF-16 
     f << L"кошка 日本国\n"; 
    } 
} 
+0

Funziona solo con il supporto C++ 11 in VC10 +. –

+1

@NicolBolas Il primo esempio utilizza wstring_convert da C++ 11, ma qualsiasi altro metodo per ottenere una codifica UTF-8 funziona anche, ad es. WideCharToMultiByte. L'ultimo esempio utilizza un facet codecvt in C++ 11 per il quale non esiste una sostituzione pre-C++ 11 integrata. Gli altri due esempi non usano C++ 11. – bames53

Problemi correlati