Почему seekp/tellp ведут себя по-разному в режиме добавления?

#c #c 11

Вопрос:

Мне нужно добавить строку в существующий файл, а затем добавить в эту строку еще одно значение. seekp Для этого я использую функции tellp и. Рассмотрим следующий код:

 #include <iostream>
#include <stdlib.h>
#include <fstream>

int main(){
    //file position
    long long opos;
    //output file
    std::ofstream outfile;

    //open new file
    outfile.open("outfile.dat"); 
    outfile<<"1t2t3"<<std::endl;
    opos = outfile.tellp();
    outfile.seekp (opos-1);
    outfile<< "t4" <<std::endl;
    outfile.close();

    //appending existing file 
    outfile.open("outfile.dat", std::ios::app); 
    outfile<<"1t2t3"<<std::endl;
    opos = outfile.tellp();
    outfile.seekp (opos-1);
    outfile<< "t4" <<std::endl;
    outfile.close();    
}
 

Он состоит из двух блоков. Сначала я открываю новый файл, записываю в него строку 1 2 3n , затем возвращаюсь на один шаг назад и перезаписываю n с t4 помощью . Это работает. Однако, когда я открываю файл в режиме добавления (второй блок), кажется, что seekp я потерял позицию. Это и есть результат:

 $ cat outfile.dat 
1   2   3   4
1   2   3
    4
 

Мой вопрос заключается в том, является ли это ожидаемым поведением, и если да, то как правильно добавить дополнительное значение t4 в существующую строку, которая работает как в режиме простого открытия, так и в режиме добавления?

Изменить: основываясь на полезных комментариях ниже, измените второе открытие файла на

 outfile.open("outfile.dat", std::ios::ate | std::ios::in);
 

похоже, это решает проблему. ate стремится к концу файла только при открытии, в отличие app от того, что действительно стремится к концу после каждой операции записи. Результат сейчас таков

 $ cat outfile.dat 
1   2   3   4
1   2   3   4
 

Комментарии:

1. app стремитесь к концу потока перед каждой записью. Так что, да, это ожидаемое поведение.

2. Смотрите эту ссылку для получения дополнительной информации

3. @Eljay Вы должны опубликовать это в качестве ответа. Как и @Botond, я не знал, что app стремлюсь к концу перед каждой записью. Я думал, что это было только после открытия. Так seekp() что на самом деле это никак не влияет на файл, открытый в app режиме. Что ж, каждый день мы узнаем что-то новое 🙂

4. Подождите, пока вы не обнаружите, что нет никакой разницы между seekp файловыми потоками и seekg в них.

5. Если вы находитесь в режиме добавления, вам вообще не нужно tellp() или seekp() . Вы уже находитесь в нужном месте.