tags:

views:

61

answers:

3

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

+5  A: 

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.

Jerry Coffin
Thank you for your answer. That's exactly what I was looking for.Concerning the chars: I'm writing a stress test program for flash memory cards. I have to be able to generate patterns where every byte has a defined value. These patters are stored internally and written to a file. From time to time I read them back and compare them with the stored patterns. I'm then able to tell the exact position of the error, and check if it's reproduceable.
zitroneneis
+3  A: 

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

Martin Beckett
A: 

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....

zitroneneis