too complicated! How about a simple buffer-based stream that stores pointers into the buffer itself: bufstart bufend bufcur position in file that bufstart corresponds to file_offset API void seekg(pos, way) if (pos >= file_offset && <= bufend - bufstart) bufcur = bufstart + (pos - file_offset) else { file_offset = pos; fseek(file_offset, SEEK_BEG); fread(file, bufstart, bufsize); bufcur = bufstart; } read(target, size){ remain = bufend - bufcur; if (size < remain){ memcpy(target, bufcur, size); } else { memcpy(target, bufcur, remain); seekg(remain, cur); read(target+remain, size - remain); } tellg(){ return file_offset + bufcur - bufstart; } calling seekg causes buffer reload from disk even if the seek destination is within the buffer range template basic_istream<_CharT, _Traits>& basic_istream<_CharT, _Traits>:: seekg(off_type __off, ios_base::seekdir __dir) { // _GLIBCXX_RESOLVE_LIB_DEFECTS // DR60. Do not change _M_gcount. ios_base::iostate __err = ios_base::iostate(ios_base::goodbit); try { if (!this->fail()) { // 136. seekp, seekg setting wrong streams? const pos_type __p = this->rdbuf()->pubseekoff(__off, __dir, ios_base::in); // 129. Need error indication from seekp() and seekg() if (__p == pos_type(off_type(-1))) __err |= ios_base::failbit; } } catch(__cxxabiv1::__forced_unwind&) { this->_M_setstate(ios_base::badbit); __throw_exception_again; } catch(...) { this->_M_setstate(ios_base::badbit); } if (__err) this->setstate(__err); return *this; } from streambuf pos_type pubseekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode = ios_base::in | ios_base::out) { return this->seekoff(__off, __way, __mode); } from streambuf: seekoff is virtual and overridden by filebuf virtual pos_type seekoff(off_type, ios_base::seekdir, ios_base::openmode /*__mode*/ = ios_base::in | ios_base::out) { return pos_type(off_type(-1)); } from filebuf: seekoff is also virtual virtual pos_type seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode __mode = ios_base::in | ios_base::out); from filebuf: seekoff has a substantial body even though it's virtual... // According to 27.8.1.4 p11 - 13, seekoff should ignore the last // argument (of type openmode). template typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>:: seekoff(off_type __off, ios_base::seekdir __way, ios_base::openmode) { int __width = 0; if (_M_codecvt) __width = _M_codecvt->encoding(); if (__width < 0) __width = 0; pos_type __ret = pos_type(off_type(-1)); const bool __testfail = __off != 0 && __width <= 0; if (this->is_open() && !__testfail) { // Ditch any pback buffers to avoid confusion. _M_destroy_pback(); // Correct state at destination. Note that this is the correct // state for the current position during output, because // codecvt::unshift() returns the state to the initial state. // This is also the correct state at the end of the file because // an unshift sequence should have been written at the end. __state_type __state = _M_state_beg; off_type __computed_off = __off * __width; if (_M_reading && __way == ios_base::cur) { if (_M_codecvt->always_noconv()) __computed_off += this->gptr() - this->egptr(); else { // Calculate offset from _M_ext_buf that corresponds // to gptr(). Note: uses _M_state_last, which // corresponds to eback(). const int __gptr_off = _M_codecvt->length(_M_state_last, _M_ext_buf, _M_ext_next, this->gptr() - this->eback()); __computed_off += _M_ext_buf + __gptr_off - _M_ext_end; // _M_state_last is modified by codecvt::length() so // it now corresponds to gptr(). __state = _M_state_last; } } __ret = _M_seek(__computed_off, __way, __state); } return __ret; } from fstream.tcc: _M_seek seems to be the culprit. The call to _M_set_buffer(-1) resets _M_in_beg, _M_in_cur, and _M_in_end to the same value, which means any read() call later will trigger a re-read from disk to reload the entire buffer template typename basic_filebuf<_CharT, _Traits>::pos_type basic_filebuf<_CharT, _Traits>:: _M_seek(off_type __off, ios_base::seekdir __way, __state_type __state) { pos_type __ret = pos_type(off_type(-1)); if (_M_terminate_output()) { // Returns pos_type(off_type(-1)) in case of failure. __ret = pos_type(_M_file.seekoff(__off, __way)); if (__ret != pos_type(off_type(-1))) { _M_reading = false; _M_writing = false; _M_ext_next = _M_ext_end = _M_ext_buf; _M_set_buffer(-1); _M_state_cur = __state; __ret.state(_M_state_cur); } } return __ret; }