Не могу записать китайский символ в текстовый файл с помощью 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>
за это.