Запись в середину существующего двоичного файла С++

Я пытаюсь открыть двоичный файл для записи без стирания содержимого. Но я не хочу писать. Я хочу написать определенную позицию в файле.

Вот пример litte:

ofstream out("test.txt", ios::binary | ios::app);
for(int i = 0; i < 100; i++)
    out.put('_');
out.write("Hallo", 5);
out.close();

ofstream out2("test.txt", ios::binary | ios::app);
out2.seekp(10);
out2.write("Welt", 4);
out2.close();

При использовании приложения поиск не работает. Если не используется файл открытия приложения, он удаляет данные. Кто-нибудь знает ответ?

Ответ 1

попробуйте вторую перегрузку seekp, которая позволяет вам предоставить смещение и направление, это может быть начало файла в вашем случае (т.е. ios_base::beg). Это, конечно, предполагает, что вы знаете, что делаете, и все, что вы хотите сделать, это перезаписать существующее количество символов.

EDIT: здесь приведен полный рабочий пример:

#include <iostream>
#include <fstream>

using namespace std;
int main()
{
  {
    ofstream out("test.txt", ios::binary);
    for(int i = 0; i < 100; i++)
      out.put('_');
    out.write("Hallo", 5);
  }

  {   
    fstream out2("test.txt", ios::binary | ios::out | ios::in);
    out2.seekp(10, ios::beg);
    out2.write("Welt", 4);
  }
}

Ответ 2

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

Ответ 3

При открытии с помощью ios:: app, как будто вы открываете новый файл, который только что был прикреплен к существующему файлу: вы не можете получить доступ к существующему файлу. Я не уверен, потому что я бы сделал так, как в ответе Керрека, но если вы действительно хотите попробовать, вам, вероятно, придется открывать " ios:: in | ios:: out", аналогично fopen ( "test.txt", "rw" ).

Или, как указывает crashmstr: ios:: out может быть достаточно.

Ответ 4

В соответствии со спецификацией fstream здесь

fstream:: open

ios:: app "Устанавливает индикатор положения потока в конец потока перед выходом EACH." Таким образом, ios:: app не работает для замены, запросы любого типа не работают, по крайней мере для меня.

Просто использование ios:: out уничтожает содержимое файла, сохраняя только размер, в основном превращая файл в корзину.

ios:: in | ios:: out оказался для меня единственной работой.

Ответ 5

Рабочий код: этот код ищет строку (OLD-STRING) в cout.exe и заменяет новую строку (NEW-STRING).

`#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(int argc, char *argv[])
{
  fstream ifs;
  ifs.open ("C:\\Users\\user\\Desktop\\cout.exe", fstream::binary | fstream::in | fstream::out);

  std::string str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());

  size_t pos = str.find("OLD-STRING");

  if (pos != string::npos)
  {
    cout << "string found at position: " << int(pos) << endl;

    ifs.seekp(pos);

    ifs.write("NEW-STRING", 10);

  }
  else
  {
    cout << "could not find string" << endl;
  }

  if (ifs.is_open())
    ifs.close();

  return 0;
}`