Как возобновить добавление данных в файл в определенной позиции? (std::ostream, streampos, tellp/seekp)

Я пытаюсь добавить некоторые данные в файл, но в некоторых случаях хочу немного вернуться назад с конца, чтобы перезаписать конец файла. Однако ни seekp( pos ), ни seekp( offset, relative ) на меня не действуют (кроме жалоб при использовании отрицательного смещения). Я использую их неправильно или они сломаны?

Далее следует небольшой пример. Компилятор: gcc версии 4.4.4 (Debian 4.4.4-6)

    #include <fstream>
    #include <sstream>
    #include <boost/date_time/posix_time/posix_time.hpp>
    using namespace std;
    using namespace boost::posix_time;

    int main(int nargs, char** pargs){
    if( nargs < 2 || nargs > 3 ){
     cerr<<"Usage: "<<pargs[0]<<" file [pos]"<<endl;
     return 1;
 }

 const char* fname = pargs[1];
 ofstream f( fname, ios::binary|ios::out|ios::ate );
 if( !f.good() ){
     cerr<<"Unable to open file!"<<endl;
     return 1;
 }

 if( nargs == 3 ){
     istringstream offss(pargs[2]);
     streamoff off;
     offss >> off;
     cout <<"Seeking to: "<<off<<endl;
     f.seekp( off, ios_base::end ); // using beg or cur instead doesn't help, nor does: seekp( off )
     if( f.fail() ){
  cerr<<"Unable to seek!"<<endl;
  f.clear(); // clear error flags
     }
 }

 f<<"[appending some data at "<<second_clock::local_time()<<"]\n";

 return 0;
    }

Теперь, если я ищу, используя смещение 0, он должен поместить выходную позицию в конец файла, и записи должны добавляться, верно? Ну, на меня это не действует (ранее osf не был пуст):

> ./ostream_app_pos osf 0
Seeking to: 0
> cat osf
[appending some data at 2010-Jul-21 11:16:16]

Обычный способ добавления — использовать ios::app. В этом случае добавление работает, но попытка поиска со смещением neg/pos не имеет никакого эффекта, поскольку (из документа gcc):

ios::app Ищет конец файла перед каждой записью.

Я также пытался использовать ни ios::ate, ни ios::app (предположительно режим усечения), с тем же эффектом, что и ios::ate.

Извините, если это больше похоже на отчет об ошибке, но я хотел проверить, есть ли что-то неправильное в использовании seekp, и понять, зависит ли это от компилятора.


person dhardy    schedule 21.07.2010    source источник
comment
Я не эксперт в этом, но попробуйте использовать std::fstream вместо ofstream и используйте std::ios::in при открытии файла; Я немного разбираюсь во внутреннем устройстве файловых потоков и думаю, что это могло бы помочь.   -  person Tomaka17    schedule 21.07.2010
comment
Бриль, спасибо! Любая идея, если это только для gcc или обычное дело? Я попробую протестировать хотя бы MSVC в ближайшее время, но здесь он не установлен...   -  person dhardy    schedule 22.07.2010


Ответы (1)


Вам нужно открыть файл как с входными, так и с выходными атрибутами.
В следующем коде нет обычной обработки ошибок, он просто иллюстрирует прием.

#include <iostream>
#include <fstream>

int main()
{
    const char *szFname = "c:\\tmp\\tmp.txt";
    std::fstream fs(szFname, 
                    std::fstream::binary | 
                    std::fstream::in     | 
                    std::fstream::out);
    fs.seekp(13, std::fstream::beg);
    fs << "123456789";

    return 0;
}

================================================

C:\Dvl\Tmp>type c:\tmp\tmp.txt
abdcefghijklmnopqrstuvwxyz
C:\Dvl\Tmp>Test.exe
C:\Dvl\Tmp>type c:\tmp\tmp.txt
abdcefghijklm123456789wxyz
C:\Dvl\Tmp>
person Michael J    schedule 01.08.2010
comment
Спасибо. На самом деле это тот же ответ, который уже дал Tomaka17! - person dhardy; 02.08.2010