И так проблема: не удаётся даже относительно передвигаться по потоку fstream/ifstream/ofstream. Плюс в добавок нельзя узнать позицию за пределами 2 Гб (ftellg).
Обе проблемы есть в Visual Studio 2008 SP1. (VS 9.0).
Сразу рекомендую переходить на 2010 и более свежую VS.
Visual Studio 2008 SP 1 (9.0), Visual Studio 2005
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 |
virtual pos_type __CLR_OR_THIS_CALL seekoff(off_type _Off, ios_base::seekdir _Way, ios_base::openmode = (ios_base::openmode)(ios_base::in | ios_base::out)) { // change position by _Off fpos_t _Fileposition; if (_Mysb::gptr() == &_Mychar // something putback && _Way == ios_base::cur // a relative seek && _Pcvt == 0) // not converting _Off -= (off_type)sizeof (_Elem); // back up over _Elem bytes if (_Myfile == 0 || !_Endwrite() || (_Off != 0 || _Way != ios_base::cur) && fseek(_Myfile, (long)_Off, _Way) != 0 || fgetpos(_Myfile, &_Fileposition) != 0) return (pos_type(_BADOFF)); // report failure if (_Mysb::gptr() == &_Mychar) _Mysb::setg(&_Mychar, &_Mychar + 1, &_Mychar + 1); // discard any putback return (_POS_TYPE_FROM_STATE(pos_type, _State, _Fileposition)); // return new position } virtual pos_type __CLR_OR_THIS_CALL seekpos(pos_type _Pos, ios_base::openmode = (ios_base::openmode)(ios_base::in | ios_base::out)) { // change position to _Pos fpos_t _Fileposition = _POS_TYPE_TO_FPOS_T(_Pos); off_type _Off = (off_type)_Pos - (off_type)_FPOSOFF(_Fileposition); if (_Myfile == 0 || !_Endwrite() || fsetpos(_Myfile, &_Fileposition) != 0 || _Off != 0 && fseek(_Myfile, (long)_Off, SEEK_CUR) != 0 || fgetpos(_Myfile, &_Fileposition) != 0) return (pos_type(_BADOFF)); // report failure _State = _POS_TYPE_TO_STATE(_Pos); if (_Mysb::gptr() == &_Mychar) _Mysb::setg(&_Mychar, &_Mychar + 1, &_Mychar + 1); // discard any putback return (_POS_TYPE_FROM_STATE(pos_type, _State, _Fileposition)); // return new position } |
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
// STREAM POSITIONING TYPES (from <streambuf>) #ifdef _WIN64 typedef __int64 streamoff; typedef __int64 streamsize; #else /* _WIN64 */ typedef long streamoff; typedef int streamsize; #endif /* _WIN64 */ #if defined(_FSEEK_OFF) #elif defined(_WIN64) #define _FSEEK_OFF(str, off, way) fseek(str, off, way) #else /* _WIN64 */ #define _FSEEK_OFF(str, off, way) _fseeki64(str, off, way) #endif /* _WIN64 */ #ifdef _M_CEE_PURE extern fpos_t& _Fpz; extern const streamoff& _BADOFF; #else extern _CRTDATA2 _PGLOBAL fpos_t _Fpz; extern _CRTDATA2 _PGLOBAL const streamoff _BADOFF; #endif // TEMPLATE CLASS fpos (from <streambuf>) template<class _Statetype> class fpos { // store arbitrary file position typedef fpos<_Statetype> _Myt; public: __CLR_OR_THIS_CALL fpos(streamoff _Off = 0) : _Myoff(_Off), _Fpos(0), _Mystate(_Stz) { // construct with stream offset } __CLR_OR_THIS_CALL fpos(_Statetype _State, fpos_t _Fileposition) : _Myoff(0), _Fpos(_Fileposition), _Mystate(_State) { // construct with conversion state and C file position } _Statetype __CLR_OR_THIS_CALL state() const { // return conversion state return (_Mystate); } void __CLR_OR_THIS_CALL state(_Statetype _State) { // set conversion state _Mystate = _State; } fpos_t __CLR_OR_THIS_CALL seekpos() const { // return C file position return (_Fpos); } __CLR_OR_THIS_CALL operator streamoff() const { // return offset return ((streamoff)(_Myoff + _FPOSOFF(_Fpos))); } //........................ private: _PGLOBAL static const _Statetype _Stz; // initial conversion state streamoff _Myoff; // stream offset fpos_t _Fpos; // C file position _Statetype _Mystate; // current conversion state }; |
150 151 152 153 154 155 156 157 |
#if !__STDC__ /* At this point we could switch both to long long, but we won't do that till next version to avoid any potential compat issues */ typedef __int64 fpos_t; #define _FPOSOFF(fp) ((long)(fp)) #else /* !__STDC__ */ typedef long long fpos_t; #define _FPOSOFF(fp) ((long)(fp)) #endif /* !__STDC__ */ |
1. Абсолютное смещение в fpos (fpos_t) хранится в 64битном типе как подобает (достать его можно при помощи seekpos()).
2. tellg и тому подобные функции не работают, потому что используют 32битную версию fseek(). (Хотя явно напрашивается использование макроса _FSEEK_OFF)
Решение 0. Использовать Visual Studio 2010 — там всё ок.
Решение 13. Написать свой блекджек. Делаем свой ownifstream (наследуюясь от basic_istream
Решениe 13-1. Попроще: всё также, только наследоваться от istream/ostream/filebuf. И использовать для определения позиции только myStream.tellg().seekpos().
Builder: Embarcadero RAD Studio XE2
fpos_t — long (stdio.h)
streamoff — _Longlong (fpos приводится к этому типу, например my_ifstream.tellg() возарщает fpos)
использует fseek с типом long для смещения указателя по файлу