问题
I'm trying to set the internal buffer of an input stream, but my implementation in C++17 doesn't implement pubsetbuf() for istringstream.
I've tried some other techniques, but they are slow or copy the original buffer. I'm looking for a fast method that doesn't do any copying.
It's closely related to this question about an output stream: Setting the internal buffer used by a standard stream (pubsetbuf)
I've followed it closely, but the buffer for the input stream remains uninitialised/empty.
// Modified template from the other question about an output stream.
// This is for an input stream, but I can't get it to work.
template <typename char_type>
struct istreambuf : public std::basic_streambuf<char_type, std::char_traits<char_type> >
{
istreambuf(char_type* buffer, std::streamsize buffer_length)
{
// Set the "put" pointer to the start of the buffer and record its length.
this->setp(buffer, buffer + buffer_length);
}
};
int main()
{
ifstream infile(FILENAME, std::ifstream::binary);
if (!infile.is_open())
{
cerr << endl << "Failed to open file " << FILENAME << endl;
return 0;
}
// Works, but slow.
//istringstream local_stream;
//local_stream << infile.rdbuf();
// Works, but creates a copy.
//istringstream local_stream(&buffer[0]);
// Works, but creates a copy.
//local_stream.str(&buffer[0]);
// Read entire file into buffer.
infile.seekg(0, std::ios::end);
streampos length = infile.tellg();
infile.seekg(0, std::ios::beg);
vector<char> buffer(length);
//char* buffer = new char[length];
infile.read(&buffer[0], length);
// Doesn't work, but should point to original.
// It returns "this" (does nothing).
//local_stream.rdbuf()->pubsetbuf(&buffer[0], length);
// Works, but deprecated in C++98.
//std::istrstream local_stream(&buffer[0]);
//local_stream.rdbuf()->pubsetbuf(&buffer[0], length);
// I followed the example in the other question about an output stream,
// but I modified for an input stream. I can't get it to work. Any ideas?
istreambuf<char> istream_buffer(&buffer[0], length);
istream local_stream(&istream_buffer);
string str1, str2;
while (local_stream >> str1 && local_stream >> str2)
{
. . .
}
}
回答1:
I've solved it! Spot the difference.
template <typename char_type> struct istreambuf : public std::basic_streambuf<char_type, std::char_traits<char_type> > { istreambuf(char_type* buffer, std::streamsize buffer_length) { // Set the "put" pointer to the start of the buffer and record its length. //this->setp(buffer, buffer + 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); } };
I needed to set the "get" pointer, not the "put" pointer. It works well now.
来源:https://stackoverflow.com/questions/56283357/internal-buffer-used-by-standard-input-stream-pubsetbuf