Visual Studio std:: stringstream pubsetbuf не работает

pubsetbuf член std:: stringbuf вообще не работает в Visual Studio 2010!

Код:

char *FileData = ... ;
unsigned long long FileDataLen = ... ;
std::stringstream *SS = new std::stringstream(std::stringstream::in | std::stringstream::out);
SS->rdbuf()->pubsetbuf( FileData, (std::streamsize)FileDataLen );

pubsetbuf ничего не делает в Visual Studio!!!

Обходной путь № 1:

std::stringstream *SS = new std::stringstream( std::string(FileData, (size_type)FileDataLen ) ),std::stringstream::in | std::stringstream::out);

Обходной путь №2:

SS->rdbuf()->sputn(FileData, (streamsize)FileDataLen);

Но обе эти обходные пути создают ненужное копирование памяти. Мне определенно нужен рабочий pubsetbuf член std:: stringbuf.

Ответ 1

putsetbuf имеет смысл только для fstream (технически для std::basic_filebuf), где буфер и поток - две разные вещи.

Для stringstream (технически, std::basic_stringbuf) они являются одним и тем же std::string.

Если вам нужен поток, который работает со строкой, внешней по отношению к нему, рассмотрите std::strstream: или boost::iostreams::array_sink

Ответ 2

basic_ios.clear() Если вам нужно изменить rdbuf, вызовите это первым или он не сработает.

std::ifstream file("file1.txt"); // file1.txt contains "Welcome!"
std::stringstream ss;
ss << file.rdbuf();

std::cout << ss.str() << std::endl;

Вывод "Добро пожаловать!".
Повторите попытку с новым файлом.

// Empty it
file.close();
ss.str("");

// New file
file.open("file2.txt"); // file2.txt contains "Goodbye!"
ss << file.rdbuf();

std::cout << ss.str() << std::endl;

Не выводит ничего.

ss.clear();
ss << file.rdbuf();
std::cout << ss.str() << std::endl;
file.close();

Вывод "До свидания!"

Ответ 3

Я вижу то же самое. Я работаю над сценариями, которые определенно не могут позволить себе делать ненужные копии данных. Кажется, что это как-то преднамеренно по комментариям в классе basic_streambuf:

virtual basic_streambuf *__CLR_OR_THIS_CALL setbuf(_Elem *, streamsize)
    {   // offer buffer to external agent (do nothing)
    return (this);
    }

Ответ 4

Недавно я столкнулся с той же проблемой setbuf, не реализованной в Visual Studio 2017.

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

Выходной поток

Source: настройка внутреннего буфера, используемого стандартным потоком (pubsetbuf)

#include <streambuf>

template <typename char_type>
struct ostreambuf : public std::basic_streambuf<char_type, std::char_traits<char_type> >
{
    ostreambuf(char_type* buffer, std::streamsize bufferLength)
    {
        // set the "put" pointer the start of the buffer and record it's length.
        setp(buffer, buffer + bufferLength);
    }
};

Входной поток

Источник: внутренний буфер, используемый стандартным входным потоком (pubsetbuf)

#include <streambuf>

template <typename char_type>
struct istreambuf : public basic_streambuf<char_type, char_traits<char_type>>
{
    istreambuf(char_type* buffer, streamsize buffer_length)
    {
        // Set the "get" pointer to the start of the buffer, the next item, and record its length.
        this->setg(buffer, buffer, buffer + buffer_length);
    }
};

int main()
{
    ifstream infile(FILENAME, ifstream::binary);

    // Read entire file into buffer.
    infile.seekg(0, ios::end);
    streampos length = infile.tellg();
    infile.seekg(0, ios::beg);
    vector<char> buffer(length);
    //char* buffer = new char[length];
    infile.read(&buffer[0], length);
    infile.close();

    // Create buffer and point local_stream to it.
    istreambuf<char> istream_buffer(&buffer[0], length);
    istream local_stream(&istream_buffer);

    string str1;

    while (local_stream >> str1)
    {
        . . .
    }
}