STL и UTF-8 файл ввода / вывода. Как это сделать?
Я использую wchar_t
для внутренних строк и UTF-8 для хранения в файлах. Мне нужно использовать STL для ввода / вывода текста на экран, а также сделать это с помощью полной литовской кодировки.
Это все нормально, потому что я не обязан делать то же самое для файлов, поэтому следующий пример отлично справляется со своей задачей:
#include <io.h>
#
include
#
включить
_setmode (_fileno(stdout), _O_U16TEXT);
wcout << L"AaĄąfl" << endl;
Но мне стало любопытно, и я попытался сделать то же самое с файлами, но безуспешно. Конечно, я мог бы использовать форматированный ввод / вывод, но это... не рекомендуется. FILE* fp;
_wfopen_s (&fp, L"utf-8_out_test.txt", L"w");
_setmode (_fileno (fp), _O_U8TEXT);
_fwprintf_p (fp, L"AaĄą\nfl");
fclose (fp);
_wfopen_s (&fp, L"utf-8_in_test.txt", L"r");
_setmode (_fileno (fp), _O_U8TEXT);
wchar_t text[256];
fseek (fp, NULL, SEEK_SET);
fwscanf (fp, L"%s", text);
wcout << text << endl;
fwscanf (fp, L"%s", text);
wcout << text << endl;
fclose (fp);
Этот фрагмент отлично работает (хотя я не уверен, как он обрабатывает неправильно сформированные символы). Итак, есть ли способ:- получить
FILE*
или целочисленный дескриптор файла формируетstd::basic_*fstream
? - моделировать
_setmode ()
в теме? - простираться
std::basic_*fstream
так он обрабатывает ввод / вывод UTF-8?
Да, я учусь в университете, и это в некоторой степени связано с моими заданиями, но я пытаюсь понять это для себя. Это не повлияет на мою оценку или что-то в этом роде.
5 ответов
Используйте шаблон std:: codecvt_facet для выполнения преобразования.
Вы можете использовать стандартную std::codecvt_byname или нестандартную реализацию codecvt_facet.
#include <locale>
using namespace std;
typedef codecvt_facet<wchar_t, char, mbstate_t> Cvt;
locale utf8locale(locale(), new codecvt_byname<wchar_t, char, mbstate_t> ("en_US.UTF-8"));
wcout.pubimbue(utf8locale);
wcout << L"Hello, wide to multybyte world!" << endl;
Помните, что на некоторых платформах codecvt_byname может выполнять преобразование только для локалей, установленных в системе.
Ну, после некоторого тестирования я понял, что FILE
принимается за _iobuf
(в w*fstream
конструктор). Итак, следующий код делает то, что мне нужно.
#
включить
#
включить
#
включить
#
include
//Для записи
FILE* fp;
_wfopen_s (&fp, L"utf-8_out_test.txt", L"w");
_setmode (_fileno (fp), _O_U8TEXT);
wofstream fs (fp);
fs << L"ąfl";
fclose (fp);
// И читаю
FILE* fp;
_wfopen_s (&fp, L"utf-8_in_test.txt", L"r");
_setmode (_fileno (fp), _O_U8TEXT);
wifstream fs (fp);
массив wchar_t [6];
fs.getline (массив, 5);
wcout << array << endl;// Для отладки
fclose (fp);
Этот пример читает и записывает легальные файлы UTF-8 (без BOM) в Windows, скомпилированные с Visual Studio 2k8.Может кто-нибудь дать какие-либо комментарии по поводу переносимости? Улучшения?
Самым простым способом было бы сделать преобразование в UTF-8 самостоятельно, прежде чем пытаться выводить. Вы можете получить некоторое вдохновение от этого вопроса: UTF8 в / из широкого преобразования символов в STL
получить FILE* или целочисленный дескриптор файла формы std::basic_*fstream?
Вы не можете заставить STL напрямую работать с UTF-8. Основная причина в том, что STL косвенно запрещает использование символов, состоящих из нескольких символов. Каждый символ должен быть один символ / wchar_t.
Microsoft фактически нарушает стандарт своей кодировкой UTF-16, так что, возможно, вы можете получить вдохновение там.