Записать wstring в wofstream или преобразование wstring в массив байтов

Рейтинг: 0Ответов: 2Опубликовано: 02.03.2023

Выдаёт код code=3221226505 при запуске.

В файл ничего не записывается.

#include <iostream>
#include <string>
#include <fstream>
#include <io.h>
#include <fcntl.h>
using namespace std;

int main () {

    setmode(_fileno(stdout), _O_U16TEXT);
    setmode(_fileno(stdin),  _O_U16TEXT);
    setmode(_fileno(stderr), _O_U16TEXT);

    wofstream file;
    file.open(L"Test.txt");
    wstring wstr = L"Кириллица";

    try {
        file << wstr;
    } catch (exception &e) {
        wcout << e.what() << endl;
    }
    file.close();
    return 0;
}

Возможен второй вариант - перевод wstring в массив байтов (char) и последующая запись этих байтов в файл:

введите сюда описание изображения

Такой код работает корректно:

#include <iostream>
#include <string>
#include <fstream>
#include <io.h>
#include <fcntl.h>
using namespace std;

int main () {

    setmode(_fileno(stdout), _O_U16TEXT);
    setmode(_fileno(stdin),  _O_U16TEXT);
    setmode(_fileno(stderr), _O_U16TEXT);

    ofstream file;
    ifstream in; // UTF-8 файл !!!
    in.open("Test_in.txt", ios::binary);
    file.open("Test.txt", ios::binary);

    char buf;
    char &buffer = buf;

    try {
        while (in.get(buffer)) file << buf;
    } catch (exception &e) {
        wcout << e.what() << endl;
    }
    file.close();
    return 0;
}

Но проблема в том, что wstring я получаю не из файла. Кто-то знает способ перевода wstring в массив char?

Ответы

▲ 0

Ввод-ввывод в С++ с использованием стандартной библиотеки - это боль... Вот работающий пример, однако следует учитывать, что начиная с С++17 codecvt_utf16 не должен использоваться. Кроме того, некорректно обрабатывается ::std::endl, поэтому окончание строки следует добавлять символами.

#include <codecvt>
#include <iostream>
#include <fstream>
#include <locale>
#include <memory>
#include <string>
#include <io.h>
#include <fcntl.h>

int main ()
{
    ::_setmode(::_fileno(stdout), _O_U16TEXT);
    ::_setmode(::_fileno(stdin),  _O_U16TEXT);
    ::_setmode(::_fileno(stderr), _O_U16TEXT);

    auto const & sz_file_name{L"Test.txt"};
    ::std::wofstream file{};
    ::std::locale const locale
    {
        file.getloc()
    ,   new ::std::codecvt_utf16
        <
            wchar_t
        ,   0xFFFF
        ,   static_cast<::std::codecvt_mode>
            (
                static_cast<unsigned int>(::std::little_endian)
                bitor
                static_cast<unsigned int>(::std::consume_header)
            )
        >
        {}
    };
    file.imbue(locale);
    // сначала записывается BOM в бинарном режиме
    file.open
    (
        sz_file_name
    ,   static_cast<::std::ios_base::openmode>
        (
            static_cast<unsigned int>(::std::ios_base::out)
            bitor 
            static_cast<unsigned int>(::std::ios_base::trunc)
            bitor 
            static_cast<unsigned int>(::std::ios_base::binary)
        )
    );
    wchar_t const bom{0xFEFF};
    file.write(::std::addressof(bom), ::std::streamsize{1});
    file.close();
    if (file.fail())
    {
        ::std::wcout << "fail\r\n" << ::std::flush;
        exit(1);
    }
    if (file.bad())
    {
        ::std::wcout << "bad\r\n" << ::std::flush;
        exit(1);
    }
    if (file.eof())
    {
        ::std::wcout << "eof\r\n" << ::std::flush;
        exit(1);
    }
    // затем дописывается текст в текстовом режиме
    file.open
    (
        sz_file_name
    ,   static_cast<::std::ios_base::openmode>
        (
            static_cast<unsigned int>(::std::ios_base::out)
            bitor 
            static_cast<unsigned int>(::std::ios_base::app)
        )
    );
    ::std::wstring wstr{L"Кириллица"};
    file << wstr;
    file.close();
    if (file.fail())
    {
        ::std::wcout << "fail\r\n" << ::std::flush;
    }
    if (file.bad())
    {
        ::std::wcout << "bad\r\n" << ::std::flush;
    }
    if (file.eof())
    {
        ::std::wcout << "eof\r\n" << ::std::flush;
    }
    return 0;
}
▲ -1

Так-как основная задача - запись wstring в файл и потом программное чтение и получение такого-же wstring, то можно считать вопрос решённым:

#include <iostream>
#include <string>
#include <fstream>
#include <io.h>
#include <fcntl.h>
using namespace std;

int main () {

    setmode(_fileno(stdout), _O_U16TEXT);
    setmode(_fileno(stdin),  _O_U16TEXT);
    setmode(_fileno(stderr), _O_U16TEXT);

    ofstream file;
    ifstream in;
    in.open("Test.txt", ios::binary);
    file.open("Test.txt", ios::binary);

    wstring str = L"Кириллица";

    unsigned int ii = 0;
    unsigned int &i = ii;

    while (i < size(str)) {
        file << str[i] << "/";
        i++;
    }
    file.close();

    char buf;
    char &buffer = buf;

    wstring temp;

    while (in.get(buffer)) {
        if (buffer == '/') {
            wcout << (wchar_t)stoi(temp.c_str());
            temp.clear();
            continue;
        }
        temp.push_back(buffer);
    }
    in.close();



    
    wcin.get();
    return 0;
}

Хоть и запись неэффективна (2 байта переводятся в int16 и записываются в десятеричной системе, на каждую цифру один байт), всё-равно, файлы небольшие, меня это устраивает.

Может кто знает способ получше?