Запись в середину существующего двоичного файла С++
Я пытаюсь открыть двоичный файл для записи без стирания содержимого. Но я не хочу писать. Я хочу написать определенную позицию в файле.
Вот пример 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;
}`