Lire le fichier Unicode UTF-8 dans wstring

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

29
demandé sur Mr.C64 2011-01-23 21:04:36

6 réponses

avec le support C++11, Vous pouvez utiliser std::codecvt_utf8 facet qui encapsule la conversion entre une chaîne D'octets encodée UTF-8 et la chaîne de caractères UCS2 ou UCS4 et qui peut être utilisée pour lire et écrire des fichiers UTF-8, texte et binaire.

pour utiliser facet vous créez habituellement locale object qui encapsule l'information propre à la culture comme 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 ceci:

std::wstring wstr = readFile("a.txt");

alternativement vous pouvez définir la locale c++ globale avant de travailler avec les flux de chaîne de caractères qui provoque tous les appels futurs à la std::locale constructeur par défaut pour retourner une copie de la locale c++ globale (vous n'avez pas besoin d'y intégrer explicitement des tampons stream):

std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
24
répondu LihO 2012-05-15 19:18:19

selon un commentaire de @Hans Passant, la manière la plus simple est d'utiliser _wfopen_s . Ouvrez le fichier en mode rt, ccs=UTF-8 .

Voici une autre solution pure 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 fonctionner aussi bien) et la wchar_t* surcharge du basic_ifstream constructeur, cela devrait même être assez conforme à la norme (où "standard" signifie C++0x, bien sûr).

13
répondu Philipp 2011-01-23 23:30:05

Voici une fonction spécifique à la plate-forme pour Windows seulement:

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

utiliser comme suit:

std::wstring mytext = LoadUtf8FileToString(L"C:\MyUtf8File.txt");

notez que le fichier entier est chargé en mémoire, donc vous ne voudrez peut-être pas l'utiliser pour de très gros fichiers.

5
répondu AshleysBrain 2011-08-11 15:41:32
#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();
}
1
répondu Shen Yu 2017-11-03 05:41:43

cette question a été abordée dans confus au sujet de C++'S std::wstring, UTF-16, UTF-8 et l'affichage de 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 UTF-16. Cette activité est strictement deux octets standard. Je crois que ce couvre arabe.

0
répondu ThomasMcLeod 2017-05-23 12:25:40

c'est un peu brut, mais que diriez-vous de lire le fichier comme de vieux octets puis de lancer le tampon byte vers wchar_t* ?

quelque chose comme:

#include <iostream>
#include <fstream>
std::wstring ReadFileIntoWstring(const std::wstring& filepath)
{
    std::wstring wstr;
    std::ifstream file (filepath.c_str(), std::ios::in|std::ios::binary|std::ios::ate);
    size_t size = (size_t)file.tellg();
    file.seekg (0, std::ios::beg);
    char* buffer = new char [size];
    file.read (buffer, size);
    wstr = (wchar_t*)buffer;
    file.close();
    delete[] buffer;
    return wstr;
}
-3
répondu dlchambers 2012-10-18 20:53:44