user2530952
user2530952

Reputation: 13

C++ edit a binary file with another

Solved! thanks all of you very much. My day has been made!(well morning, its 4am)

I'm trying to write a program in C++ that opens a .dat file in binary and replaces the first 1840 hex characters with that of another .dat file, while leaving the remaining hex values of the first .dat file the same. I have spent about 12 hours on this today and have had little success. I am a beginner programmer, I have taken one semester worth of c++ courses and we did not get to streams.

(it opens a file and everything, but deletes every thing after the new values have been added)

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <cmath>
#include <cstring>
using namespace std;



int main (){

string filename;
long size;
char* memblock;

   cout << " Enter a file to be modded by Mod.dat  ";
   cin >> filename;

    ofstream infile ( filename ,std::ofstream::binary);
    //filename: the file that will be opened and changed)

    ifstream modFile ("Mod.dat", ifstream::binary);
    // (mod.dat is the file that i get the first 1840 hex values from)




modFile.seekg (0,modFile.end);
size = modFile.tellg();
memblock = new char [size];
modFile.seekg (0, ios::beg);
    modFile.read (memblock, size);

infile.write(memblock, 1840);

modFile.close();
infile.close();


cout << endl;
return 0;
}

Any help would be greatly appreciated, I hope there is some simple way to do this.

Solved! thanks all of you very much. My day has been made!(well morning, its 4am)

Upvotes: 1

Views: 3774

Answers (2)

Mats Petersson
Mats Petersson

Reputation: 129314

My preferred fix, although Matthieu Rouget's fix does indeed work, is to just add ofstreeam::in to the opening of the input file:

ofstream infile ( filename.c_str(), std::ofstream::binary | ofstream::in);

(I had to use c_str() in my build, as glibc in my version doesn't take std::string as input).

I tested this on my local system (it took a while to realize that mod.dat is actually "Mod.dat"!)

It is probably a good idea to also check that the files actually opened, so something like this after ofstream infile line:

if (!infile)
{
cout << "Couldn't open " << filename << endl;
}

and similar for the modfile line.

And since you go through the effort of figuring out what the first part of the modfile size is, I would suggest that you also USE that for the writing of the file.

Upvotes: 1

Matthieu Rouget
Matthieu Rouget

Reputation: 3369

Edit:

You can modidy your file in place with something like :

std::fstream s(my_file_path, std::ios_base::binary);
s.seekp(position_of_data_to_overwrite, std::ios_base::beg);
s.write(my_data, size_of_data_to_overwrite);

std::fstream will not truncate your input file as std::ofstream does.


The other solution is to not use the same file for reading and writing. Use three files :

  • One for the output file.
  • One for the First input file.
  • One for the second input file.

fstream infile ( filename ,std::ofstream::binary); does not keeps the contents of the original file. Everything you write will erase the contents of the file.

Thus, you should:

  • open the output file
  • open the "Mod" file, read the first 1840 bytes from the first file, write them into the output file.
  • open the "main input file" file, move the cursor to 1840, read the remaining data and write it to the output file.

Depending on the "main input file" size, you may want to buffer you read/write operation.

Upvotes: 3

Related Questions