Написал в файл, используя std::wofstream. Файл остался пустым
Я написал следующую программу, используя VS2008:
#include <fstream>
int main()
{
std::wofstream fout("myfile");
fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}
Когда я попытался скомпилировать его, IDE спросила меня, хочу ли я сохранить исходный файл в Unicode, я ответил "да, пожалуйста".
Затем я запускаю программу, и myfile появился в папке моего проекта. Я открыл его с помощью блокнота, файл был пуст. Я вспомнил, что блокнот поддерживает только данные ASCII. Я открыл его с WordPad, он все еще был пустым. Наконец маленький гений внутри меня убедил меня взглянуть на размер файла, и неудивительно, что это было 0 байт. Поэтому я перестроил и перезапустил программу, безрезультатно. Наконец я решил спросить очень умных людей на Stackru о том, что мне не хватает, и вот я здесь:)
Отредактировано:
После того, как вышеупомянутые умные люди оставили некоторые комментарии, я решил последовать их совету и переписал программу следующим образом:
#include <fstream>
#include <iostream>
int main()
{
std::wofstream fout("myfile");
if(!fout.is_open())
{
std::cout << "Before: Not open...\n";
}
fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
if(!fout.good())
{
std::cout << "After: Not good...\n";
}
}
Построил это. Запустил это. И... консоль ясно прочитала, к моему удивлению: "После: не хорошо...". Поэтому я отредактировал свой пост, чтобы предоставить новую информацию, и начал ждать ответов, которые объяснили бы, почему это так и что я мог сделать.:)
3 ответа
В Visual studio выходной поток всегда записывается в кодировке ANSI и не поддерживает вывод UTF-8.
Что в основном нужно сделать, это создать класс языкового стандарта, установить в него фасет UTF-8 и затем передать его в fstream.
Что происходит, что кодовые точки не преобразуются в кодировку UTF. Так что в принципе это не будет работать под MSVC, поскольку он не поддерживает UTF-8.
Это будет работать под Linux с языком UTF-8
#include <fstream>
int main()
{
std::locale::global(std::locale(""));
std::wofstream fout("myfile");
fout << L"Հայաստան Россия Österreich Ελλάδα भारत" << std::endl;
}
~ И под окнами это будет работать:
#include <fstream>
int main()
{
std::locale::global(std::locale("Russian_Russia"));
std::wofstream fout("myfile");
fout << L"Россия" << std::endl;
}
Так как MSVC поддерживает только кодировки ANSI.
Фасет Codecvt можно найти в некоторых библиотеках Boost. Например: http://www.boost.org/doc/libs/1_38_0/libs/serialization/doc/codecvt.html
MSVC предлагает codecvt_utf8
языковой аспект для этой проблемы.
#include <codecvt>
// ...
std::wofstream fout(fileName);
std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
fout.imbue(loc);
Я обнаружил, что следующий код работает правильно. Я использую VS2019.
#include <iostream>
#include <fstream>
#include <codecvt>
int main()
{
std::wstring str = L"abàdëef€hhhhhhhµa";
std::wofstream fout(L"C:\\app.log.txt", ios_base::app); //change this to ios_base::in or ios_base::out as per relevance
std::locale loc(std::locale::classic(), new std::codecvt_utf8<wchar_t>);
fout.imbue(loc);
fout << str;
fout.close();
}