Comment puis-je lire un fichier Unicode (UTF-8) en wstring
(s) sur la plate-forme Windows ?
Réponses
Trop de publicités?Avec le support de C++11, vous pouvez utiliser std::codecvt_utf8 facet qui encapsule la conversion entre une chaîne d'octets codée UTF-8 et une chaîne de caractères UCS2 ou UCS4. y qui peut être utilisé pour lire et écrire des fichiers UTF-8, tant textuels que binaires.
Afin d'utiliser facette vous créez généralement objet local qui encapsule les informations spécifiques à une culture sous la forme d'un ensemble de facettes qui définissent collectivement un environnement localisé spécifique. Une fois que vous avez un objet local, vous pouvez imbue votre tampon de flux avec elle :
#include <sstream>
#include <fstream>
#include <codecvt>
std::wstring readFile(const char* filename)
{
std::wifstream wif(filename);
wif.imbue(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
std::wstringstream wss;
wss << wif.rdbuf();
return wss.str();
}
qui peut être utilisé comme suit :
std::wstring wstr = readFile("a.txt");
Vous pouvez également définir la locale globale C++ avant de travailler avec des flux de chaînes de caractères qui fait en sorte que tous les futurs appels à l std::locale
Constructeur par défaut pour retourner une copie de la locale globale C++. (il n'est donc pas nécessaire d'en imprégner explicitement les tampons de flux) :
std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
D'après un commentaire de @Hans Passant, le moyen le plus simple est d'utiliser _wfopen_s . Ouvrez le fichier avec le mode rt, ccs=UTF-8
.
Voici une autre solution purement C++ qui fonctionne au moins avec VC++ 2010 :
#include <locale>
#include <codecvt>
#include <string>
#include <fstream>
#include <cstdlib>
int main() {
const std::locale empty_locale = std::locale::empty();
typedef std::codecvt_utf8<wchar_t> converter_type;
const converter_type* converter = new converter_type;
const std::locale utf8_locale = std::locale(empty_locale, converter);
std::wifstream stream(L"test.txt");
stream.imbue(utf8_locale);
std::wstring line;
std::getline(stream, line);
std::system("pause");
}
Sauf pour locale::empty()
(ici locale::global()
pourrait également fonctionner) et le wchar_t*
surcharge de la basic_ifstream
cela devrait même être assez conforme à la norme (où "norme" signifie C++0x, bien sûr).
Voici une fonction spécifique à la plate-forme Windows uniquement :
size_t GetSizeOfFile(const std::wstring& path)
{
struct _stat fileinfo;
_wstat(path.c_str(), &fileinfo);
return fileinfo.st_size;
}
std::wstring LoadUtf8FileToString(const std::wstring& filename)
{
std::wstring buffer; // stores file contents
FILE* f = _wfopen(filename.c_str(), L"rtS, ccs=UTF-8");
// Failed to open file
if (f == NULL)
{
// ...handle some error...
return buffer;
}
size_t filesize = GetSizeOfFile(filename);
// Read entire file contents in to memory
if (filesize > 0)
{
buffer.resize(filesize);
size_t wchars_read = fread(&(buffer.front()), sizeof(wchar_t), filesize, f);
buffer.resize(wchars_read);
buffer.shrink_to_fit();
}
fclose(f);
return buffer;
}
Utilisez comme ça :
std::wstring mytext = LoadUtf8FileToString(L"C:\\MyUtf8File.txt");
Notez que le fichier entier est chargé en mémoire, vous ne voudrez donc peut-être pas l'utiliser pour des fichiers très volumineux.
Cette question a été abordée dans Confusion au sujet de std::wstring de C++, UTF-16, UTF-8 et de l'affichage des chaînes dans une interface graphique Windows . En résumé, wstring est basé sur la norme UCS-2, qui est le prédécesseur de l'UTF-16. Il s'agit d'une norme strictement à deux octets. Je pense que cela couvre l'arabe.
- Réponses précédentes
- Plus de réponses