Как преобразовать std :: istream в std :: wistream - PullRequest
1 голос
/ 02 октября 2011

У меня есть istream, и некоторый код ожидает wistream.

Я буквально хочу, чтобы каждый символ нулевого потока источника был расширен до wchar_t. Меня не волнуют кодовые страницы, меня не волнует локализация, я просто хочу плавно передать этот ввод, какой самый быстрый способ сделать это?

Ответы [ 2 ]

1 голос
/ 03 октября 2011

Вы можете написать буфер чтения, чтобы адаптировать базовый буфер потока в istream к вашему wistream:

class adapting_wistreambuf : public wstreambuf {
  streambuf *parent;
public:
  adapting_istreambuf(streambuf *parent_) : parent(parent_) { }
  int_type underflow() {
    return (int_type)parent->snextc();
  }
};

Позже:

istream &somestream = ...;
adapting_wistreambuf sb(somestream.rdbuf());
wistream wistream(&sb);

// now work with wistream

Это реализует только минимальный интерфейс streambuf. Вы можете добавить код управления буфером для повышения производительности, если вам нужно.

0 голосов
/ 03 октября 2011

Я думаю, что невозможно без написания сложной * оболочки вокруг std::wistream, чтобы обеспечить std::istream интерфейс.Разница между ними заключается в типе char, который используется при создании экземпляров этих классов из шаблонов, что делает std::istream (char_type = char) и std::wistream (char_type = wchar_t) в двух разных иерархиях классов.Они только разделяют std :: ios_base как общий базовый класс, который не предоставляет чего-то полезного для вашей текущей проблемы.

Из-за этого следующий фрагмент кода не будет компилироваться (пытается заменить внутреннюю std::streambuf из s2 на s1, тем самым делая операции ввода-вывода на s2, выполняющие данные из файла):

std::wifstream     s1 ;
std::istringstream s2 ;

// assuming s1 and s2 are correctly initialized ...

s2.ios::rdbuf(s1.rdbuf()) ;  // will not compile, unfortunately, unless the char type
                             // is the same for the two streams :(

Я не знаю простого решения,возможно, можно использовать Boost IOStreams Filter (я никогда не пробовал :().

Если вы не имеете дело с двоичными данными, а длина вашего потока не слишком велика, попробуйте прочитатьвсе данные в строку, а затем преобразовать ( расширение нуля , как вы говорите) в std::wistringstream.

*: сложных означает, что у вас есть разумные знания о std :: streams. Признаюсь, мне не очень комфортно с потоками.

...