Считайте файл Unicode UTF-8 в wstring - PullRequest
34 голосов
/ 23 января 2011

Как мне прочитать файл Unicode (UTF-8) в wstring на платформе Windows?

Ответы [ 6 ]

30 голосов
/ 15 мая 2012

С поддержкой C ++ 11 вы можете использовать std :: codecvt_utf8 facet , который инкапсулирует преобразование между строкой байтов в кодировке UTF-8 и строкой символов UCS2 или UCS4 и который может использоваться для чтения и записи файлов UTF-8, как текстовых, так и двоичных.

Чтобы использовать facet , вы обычно создаете объект локали , которая инкапсулирует специфическую для культуры информацию в виде набора аспектов, которые совместно определяют конкретную локализованную среду. Получив объект языкового стандарта, вы можете наполнить буфер потока с ним:

#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();
}

, который можно использовать следующим образом:

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

В качестве альтернативы вы можете установить глобальный языковой стандарт C ++ , прежде чем работать со строковыми потоками, которые вызывают все будущие вызовыв конструктор std::locale по умолчанию, чтобы вернуть копию глобальной локали C ++ (тогда вам не нужно явно загружать потоковые буферы):

std::locale::global(std::locale(std::locale::empty(), new std::codecvt_utf8<wchar_t>));
14 голосов
/ 23 января 2011

Согласно комментарию @Hans Passant, самый простой способ - использовать _wfopen_s .Откройте файл в режиме rt, ccs=UTF-8.

Вот еще одно чистое решение C ++, которое работает по крайней мере с 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");
}

За исключением locale::empty() (здесь locale::global() может работатьтакже) и перегрузка wchar_t* конструктора basic_ifstream, это должно быть даже вполне совместимым со стандартом (где «стандарт» означает, конечно, C ++ 0x).

5 голосов
/ 23 января 2011

Вот специфичная для платформы функция только для Windows:

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

Используйте вот так:

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

Обратите внимание, что весь файл загружен в память, поэтому вы можете не использовать его для очень больших файлов.

2 голосов
/ 03 ноября 2017
#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();
}
0 голосов
/ 19 октября 2012

Это немного необработанно, но как насчет чтения файла как простых старых байтов, а затем преобразования байтового буфера в wchar_t *?

Что-то вроде:

#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;
}
0 голосов
/ 23 января 2011

Этот вопрос был рассмотрен в Запутался в std :: wstring, UTF-16, UTF-8 в C ++ и отображении строк в графическом интерфейсе Windows В итоге, wstring основана на стандарте UCS-2, который является предшественником UTF-16.Это строго двухбайтовый стандарт.Я считаю, что это охватывает арабский язык.

...