Записать wstring в wofstream или преобразование wstring в массив байтов
Выдаёт код 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?
Ответы (2 шт):
Так-как основная задача - запись 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 и записываются в десятеричной системе, на каждую цифру один байт), всё-равно, файлы небольшие, меня это устраивает.
Может кто знает способ получше?
Ввод-ввывод в С++ с использованием стандартной библиотеки - это боль... Вот работающий пример, однако следует учитывать, что начиная с С++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;
}
