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)
{
. . .
}
}