STL и UTF-8 файл ввода / вывода.Как это сделать? - PullRequest
4 голосов
/ 26 октября 2010

Я использую wchar_t для внутренних строк и UTF-8 для хранения в файлах. Мне нужно использовать STL для ввода / вывода текста на экран , а также использовать полную литовскую кодировку.
Все нормально, потому что меня не заставляют делать то же самое для файлов , поэтому следующий пример отлично справляется с работой:

#include <io.h>
<code>#</code>include <fcntl.h>
<code>#</code>include <iostream>
    _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 ]

2 голосов
/ 26 октября 2010

Ну, после некоторого тестирования я понял, что FILE принимается за _iobuf (в конструкторе w*fstream). Итак, следующий код делает то, что мне нужно.

<code>#</code>include <iostream>
<code>#</code>include <fstream>
<code>#</code>include <io.h>
<code>#</code>include <fcntl.h>
//For writing
    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);
//And reading
    FILE* fp;
    _wfopen_s (&fp, L"utf-8_in_test.txt", L"r");
    _setmode (_fileno (fp), _O_U8TEXT);
    wifstream fs (fp);
    wchar_t array[6];
    fs.getline (array, 5);
    wcout << array << endl;//For debug
    fclose (fp);
Этот пример читает и записывает легитимные файлы UTF-8 (без спецификации) в Windows, скомпилированные с Visual Studio 2k8.

Может кто-нибудь дать какие-либо комментарии по поводу переносимости? Улучшения?

2 голосов
/ 26 октября 2010

Используйте шаблон 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 может выполнять преобразование только для локалей, установленных в системе.

1 голос
/ 26 октября 2010

Самый простой способ - сделать преобразование в UTF-8 самостоятельно, прежде чем пытаться выводить. Вы можете черпать вдохновение из этого вопроса: UTF8 в / из широкоугольного преобразования в STL

0 голосов
/ 26 октября 2010

получить FILE * или целочисленный дескриптор файла в виде std :: basic_ * fstream?

Ответил в другом месте.

0 голосов
/ 26 октября 2010

Вы не можете заставить STL напрямую работать с UTF-8.Основная причина в том, что STL косвенно запрещает использование символов, состоящих из нескольких символов.Каждый символ должен быть один символ / wchar_t.

Microsoft фактически нарушает стандарт своей кодировкой UTF-16, так что, возможно, вы можете получить вдохновение там.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...