Не могу записать китайский символ в текстовый файл с помощью wofstream

Я использую std::wofstream писать символы в текстовом файле. Мои символы могут иметь символы из самых разных языков (с английского на китайский). Я хочу напечатать мой vector<wstring> в этот файл. Если мой вектор содержит только английские символы, я могу напечатать их без проблем. Но если я напишу китайские символы, мой файл останется пустым.

Я просмотрел через stackru и все ответы, в основном, говорили об использовании функций из библиотеки:

#include <codecvt>

Я не могу включить эту библиотеку, потому что я использую Dev-C++ в версии 5.11. Я сделал:#define UNICODE во всех моих заголовочных файлах. Я думаю, что есть действительно простое решение для этой проблемы. Было бы здорово, если бы кто-нибудь мог мне помочь.

Мой код:

#define UNICODE
#include <string>
#include <fstream>

using namespace std;

int main()
{
    string Path = "D:\\Users\\S020697\\Desktop\\korrigiert_RotCommon_zh_check_error.log";
    wofstream Out;
    wstring eng = L"hello";
    wstring chi = L"程序";

    Out.open(Path, ios::out);

    //works.
    Out << eng;

    //fails
    Out << chi;

    Out.close();

    return 0;
}

С уважением

3 ответа

Решение

Я только разобрался, как решить эту проблему самостоятельно. Мне пришлось преобразовать мою строку в строку, используя функцию WideCharToMultiByte. Для этого я использовал эту функцию:

std::string to_utf8(const wchar_t* buffer, int len)
{
string newbuffer;
int nChars;
nChars = ::WideCharToMultiByte(CP_UTF8, 0, buffer, len, NULL, 0, NULL, NULL);

if (nChars == 0)
{
    return "";
}


newbuffer.resize(nChars);

::WideCharToMultiByte(CP_UTF8,0,buffer,len,
    const_cast<char* >(newbuffer.c_str()),nChars,NULL, NULL);

return newbuffer;
}

std::string to_utf8(const std::wstring& str)
{
return to_utf8(str.c_str(), (int)str.size());
}

В моей основной программе мне нужно было вызвать функцию как:

string chi= to_utf8(L"程序");

Спасибо всем, что нашли ответ!

Во-первых, событие имя wofstream подразумевает, что это широкий поток символов, это не так. Это все еще поток чарса. Он использует фасет конвертирования из локали для преобразования wchars в char.

Вот что говорит cppreference:

Все операции ввода-вывода файлов выполняются через std::basic_fstream<CharT> использовать std::codecvt<CharT, char, std::mbstate_t> аспект локали пропитан в потоке.

Таким образом, вы можете установить глобальную локализацию, поддерживающую китайский язык, или imbue поток. В случаях с ботами вы получите поток одного байта.

#include <locale>
//...
const std::locale loc = std::locale(std::locale(), new std::codecvt_utf8<wchar_t>);

Out.open(Path, ios::out);
Out.imbue(loc);

к несчастью std::codecvt_utf8 уже устарела [ 2]. В этой статье журнала MSDN объясняется, как сделать преобразование UTF-8 с помощью MultiByteToWideChar C++ - Преобразование кодировки Unicode с помощью STL-строк и Win32 API.

Здесь вариант Microsoft / vcpkg to_utf8 преобразование:

std::string to_utf8(const CWStringView w)
{
    const size_t size = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr);
    std::string output;
    output.resize(size - 1);
    WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, output.data(), size - 1, nullptr, nullptr);
    return output;
 }

С другой стороны вы можете использовать обычный двоичный поток и записать wstring данные с write(),

std::ofstream Out(Path, ios::out | ios::binary);

const uint16_t bom = 0xFEFF;
Out.write(reinterpret_cast<const char*>(&bom), sizeof(bom));    // optional Byte order mark

Out.write(reinterpret_cast<const char*>(chi.data()), chi.size() * sizeof(wchar_t));

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

Out.imbue(std::locale("zh_CN.UTF-8"));

Вам, очевидно, нужно будет включить <locale> за это.

Другие вопросы по тегам