44 votes

Lire un fichier Unicode UTF-8 dans wstring

Comment puis-je lire un fichier Unicode (UTF-8) en wstring (s) sur la plate-forme Windows ?

42voto

LihO Points 21648

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>));

15voto

Philipp Points 21479

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).

7voto

AshleysBrain Points 11439

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.

1voto

Shen Yu Points 91
#include <iostream>
#include <fstream>
#include <string>
#include <locale>
#include <cstdlib>

int main()
{
    std::wifstream wif("filename.txt");
    wif.imbue(std::locale("zh_CN.UTF-8"));

    std::wcout.imbue(std::locale("zh_CN.UTF-8"));
    std::wcout << wif.rdbuf();
}

0voto

ThomasMcLeod Points 2717

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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X