Better way to determine length of a std::istream?

seekg
istream seek example
tellg
streampos to int
istream::read
check if istream is empty c++
istream buffer
ifstream file size

Is there a better way to determine the length of an std::istream than the following:

std::istream* pcStream = GetSomeStream();
pcStream->seekg(0, ios::end);
unsigned int uiLength = pcStream->tellg();

It just seems really wasteful to have to seek to the end of the stream and then seek back to the original position, especially if the stream might be to a file on some slow media like a CD or DVD.

tellg() function in C++ with example, () function is used with input streams, and returns the current “get” position of the pointer in the stream. It has no parameters and returns a value of the member type pos_type, which is an integer data type representing the current position of the get stream pointer. The class istrstream implements input operations on array-backed streams. It essentially wraps a raw array I/O device implementation (std:: strstreambuf) into the higher-level interface of std::basic_istream. The typical implementation of istrstream holds only one non-derived data member: an object of type std:: strstreambuf.

In order to get the current length / size of a steam I do this:

auto size = strlen(currentStream.str().c_str());

This needs to happen before functions that will set its size to 0 such as move(currentStream).

How can I get a file's size in C++?, How do I get the size of a file in C++? The obvious solution is std::copy_n: std::copy_n( std::istreambuf_iterator<char>( is ), size, std::back_inserter( msg ) ); This will only work if you can be sure that the characters are there, however. If you encounter end of file while trying to read the characters, undefined behavior ensues.

Have you considered keeping track of the size by using istream::gcount() ?

please explain istream in simple terms - C++ Forum, Example 11-6. stream_size(): compute length of a stream std::streamoff current_pos) return -1; f.seekg(0,std::istream::end); std::istream::pos_type It's another example of how good library design makes functions more flexible and general. to provide an estimate when called on streams that cannot determine their size. Do you mean std::istream or COM IStream?How did you open it? That may determine the correct way to close it. – Rob Kennedy Mar 1 '11 at 19:15

There was some kind of stream which couldn't get length by calling tellg(). In case of, tellg() may return -1.

You could get stream length by preparing enough sized buffer. I found out how to get length by looking into stream::read function.

const int DATA_SIZE = 1024 * 512;
char buf[DATA_SIZE];  // 1024 * 512 is enough!
std::istream& is = GetSomeStream();
int Len = is.rdbuf()->sgetn(buf, DATA_SIZE);

Above, Len is real data size in istream.

Optimized C++: Proven Techniques for Heightened Performance, Another. Overloaded. Operator. Perhaps you are wondering whether we could get Probably the simplest way to do this is by defining an array of strings to hold the the compiler to use the number of initializers to determine the size of the array. Here is a suitable definition: std::ostream & operator<< (std::ostream & out,  template<typename T> std::streamsize read(T* out, std::istream& stream, size_t count=1) { stream.read(reinterpret_cast<char*>(out), sizeof(T)*count); return stream.gcount(); } If you don't care about reading arrays, you may even omit the count argument and have it even simpler. There are some ways to modify this to your own needs.

You Can Program in C++: A Programmer's Introduction, read a file into memory #include <iostream> // std::cout #include <fstream> moved with seekg to the end of the stream, therefore determining the size of the file. Extracts n characters from the stream and stores them in the array pointed to by s. This function simply copies a block of data, without checking its contents nor appending a null character at the end.

std::istream::tellg - istream::tellg, That begs the question of whether you can define a variable outside of all blocks. function deletes an element from a vector, reducing the vector's size by one. with calls to standard algorithms, which is a better way to write C++ programs std:: vectorzints data; data.insert (data.begin (), std::istream iterator&int» (std:: cin)​,  Extracts characters from the stream, as unformatted input: (1) single character Extracts a single character from the stream. The character is either returned (first signature), or set as the value of its argument (second signature).

Exploring C++: The Programmer's Introduction to C++, If count is std::numeric_limits<std::streamsize>::max() (the largest value of type std::streamsize; of cin: cin.ignore(numeric_limits<std::streamsize>::max()); int istream::peek () • Returns the Returns EOF if no more characters can be read. The difference between unget() and putback() is that for putback(), a check is made  The standard stream buffer has this functionality. Create a stream. Gets its buffer then over-ride it. #include <sstream> #include <iostream> #include <algorithm> #include <iterator> int main() { // Your imaginary buffer char buffer[] = "A large buffer we don't want to copy but use in a stream"; // An ordinary stream.

Comments
  • An API I'm using requires the size of the data I'm passing it. It uses a raw character buffer, and keeps processing it until it reaches the end of the buffer.
  • You could use a stat() on the file. However, it is not any faster than seeking at the end and seeking back at the beginning before reading the contents... that's how file descriptors are implemented. Of course, stat() is not C++ and it requires a filename...
  • I do realize expecting a length to always be available is a bit limiting to the kind of streams to be used, thankfully it's very unlikely I'll be using anything other then ifstreams and my own memstream and zipstream implementations.
  • It looks like the return type from tellg() is always numeric, based on a constraint of std::streampos.
  • I require the size for allocation of the buffer to which the data will be copied-I suppose I could allocate an initial amount and realloc thereafter, but I'm a bit worried about fragmentation (working in a limited mem environment).