Better way to determine length of a std::istream?
Question
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.
Solution
The "best" way is to avoid needing the length :)
- Not all streams are seekable (For example, imagine an istream on a network socket)
- The return type from tellg() is not necessarily numeric (the only requirement is that it can be passed back to seekg() to return to the same position)
- Even if it is numeric, it is not necessarily a number of bytes. For example, it could be a "magic" value meaning "at the end"
- For fstreams, issues like case and linefeed conversion can screw things up
OTHER TIPS
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)
.
Have you considered keeping track of the size by using istream::gcount() ?
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
.