Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update only part of a binary file with c++

Tags:

c++

stream

Is it possible to update only a part of a file in c++ ?

Example:

Old File A: 'A''A''A''B''B''C''C''C'
New File A: 'A''A''A''X''X''C''C''C'

as the real files are not as tiny like these examples, and I do know exactly what has changed ( offset and writeLenght for changed content ) it would be great to be able to open a file, set the stream to the right position, write the information and close the file again.... but this will lead to a file that looks like this:

Updated File: '0''0''0''X''X''C''C''C'

This is the code I used:

void update file( list<unsigned char> content, int offset){

fs::basic_ofstream< char > fileStream( path , ios::out | ios::binary );    
list< unsigned char >::const_iterator contentIter = content.begin();
// begin write operation at the offset
advance( contentIter , offset);
fileStream.seekp( offset );
while( contentIter != content.end() ){
    unsigned char value = (char)*contentIter;
    fileStream.put( value );
    ++contentIter;          
}
fileStream.close();

Is there a way to do this, or has the whole file to be rewritten everytime it changes ?

Thank you

like image 393
zitroneneis Avatar asked Aug 18 '10 14:08

zitroneneis


People also ask

Can a binary file be edited?

Binary files can be edited in either (or both) ASCII View or Hexadecimal View encodings, and EmEditor's large file capabilities mean that huge (up to 16 TB—that's 1,099 billion lines!) binary files are no problem (64-bit version).

Does binary file have end of file?

The file doesn't actually contain an EOF. EOF isn't a character of sorts - remember a byte can be between 0 and 255, so it wouldn't make sense if a file could contain a -1. The EOF is a signal from the operating system that you're using, which indicates the end of the file has been reached.

Do binary files have extensions?

In general, executable -- or ready-to-run -- programs are identified as binary files and given a filename extension such as . bin or .exe. Programmers often talk about an executable program as a binary or will refer to their compiled application files as binaries.


3 Answers

You have pretty much the right idea. The main thing you need to change is using an fstream instead of ofstream, and use ios::in | ios::out when you open it (assuming fs::basic_ofstream somehow resolves to std::basic_ofstream). When you open with just ios::out the existing file content is destroyed.

Edit: By the way, I have a hard time imagining a situation where using std::list<char> is a good idea. On a typical machine with 32-bit pointers and 8-bit chars, you're looking at using 8 times a much space for the pointers as you are for the data you're trying to store, and your access to the data you store is generally pretty slow as well.

like image 114
Jerry Coffin Avatar answered Oct 12 '22 23:10

Jerry Coffin


Not as c++'ish but the obvious way to do this is with memory mapped files

like image 35
Martin Beckett Avatar answered Oct 12 '22 21:10

Martin Beckett


Ok, thank you:
Here's a working piece of code in case anyone encounters the same question.

void update file( list<unsigned char> content, int offset, int writeLength){ 

fs::basic_fstream< char > fileStream( path , ios::out | ios::in | ios::binary );     
 list< unsigned char >::const_iterator contentIter = content.begin(); 
 // begin write operation at the offset 
 advance( contentIter , offset); 
 // set the Stream to the offset position
 fileStream.seekp( offset ); 
 while( contentIter != content.end() && writeLength != 0){ 
    unsigned char value = (char)*contentIter; 
    fileStream.put( value ); 
    ++contentIter; 
    --writeLength;          
 } 
fileStream.close(); 
}

One should check for errors or tell the stream to throw exceptions when using this code....

like image 26
zitroneneis Avatar answered Oct 12 '22 21:10

zitroneneis