Запись в середину существующего двоичного файла c ++ - PullRequest
13 голосов
/ 21 июня 2011

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

Вот небольшой пример:

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();

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

Ответы [ 5 ]

11 голосов
/ 21 июня 2011

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

РЕДАКТИРОВАТЬ: вот полностью рабочий пример:

#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);
  }
}
5 голосов
/ 21 июня 2011

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

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

5 голосов
/ 21 июня 2011

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

2 голосов
/ 20 июля 2011

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

fstream :: open

the ios :: app "Устанавливает индикатор позиции потока в конец потока передКАЖДАЯ выходная операция. "Таким образом, ios :: app не работает для замены, поиск любого рода завершается неудачей, по крайней мере, для меня.

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

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

0 голосов
/ 13 сентября 2012

Рабочий код: этот код ищет строку (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;
}`
...