Search code examples
cfilefile-iourl-rewritingstdio

Rewrite only first bytes of file


I have small problem with rewriting first 2,5KB of file. My code should read 2KB and 512 bytes to dynamically allocated memory and then rewrite specific bytes of much larger file.

f = fopen(argv[2], "rb");
if(f==NULL)
    printf("File doesn't exist!");
fseek(f, 0, SEEK_SET);
data = calloc(2*1024+512, 1);
fread(data, 1, 2*1024+512, f);
fclose(f);

f = fopen(argv[1], "ab");
if(f==NULL)
    printf("File doesn't exist!");
fseek(f, 0, SEEK_SET);
fwrite(data, 1, 446, f);
fseek(f, 512, SEEK_SET);
fwrite(((char*)data)+512, 1, 2*1024, f);
fclose(f);

When I try to use wb mode, it erases contents of second file. When I use ab mode and seek to the start of file, previous content is appended on the end.

Is there any way (using standard C libraries) to rewrite file contents without appending and copying remaining content of written file? Please help.


Solution

  • The "rb" mode opens the file positioned at the start; the initial fseek() is redundant.

    The second open with "ab" opens the file for writing in append mode. All writes will occur at the end of the file, regardless of what fseek() operations you do beforehand.

    You could sensibly use mode "rb+" to open the file once for both reading and writing:

    if ((f = fopen(argv[2], "rb+")) != 0)
    {
        char *data = calloc(2*1024+512, 1);   // Missing error check
        fread(data, 1, 2*1024+512, f);        // Missing error check
        // Modify data?
        fseek(f, 0, SEEK_SET);
        fwrite(data, 1, 446, f);
        fseek(f, 512, SEEK_SET);
        fwrite(((char*)data)+512, 1, 2*1024, f);
        fclose(f);
    }
    

    The code should check that the calloc() succeeds before using data; it should also error check the fread() to be sure it got the expected data. Presumably, something in the middle will modify the data read from the file.


    ISO/IEC 9899:2011 (the current C standard) has this to say about the modes for fopen() — and the previous standards said much the same except for the x flag, which is new in C11:

    §7.21.5.3 The fopen function

    ¶3 The argument mode points to a string. If the string is one of the following, the file is open in the indicated mode. Otherwise, the behavior is undefined.271)

    • r open text file for reading
    • w truncate to zero length or create text file for writing
    • wx create text file for writing
    • a append; open or create text file for writing at end-of-file
    • rb open binary file for reading
    • wb truncate to zero length or create binary file for writing
    • wbx create binary file for writing
    • ab append; open or create binary file for writing at end-of-file
    • r+ open text file for update (reading and writing)
    • w+ truncate to zero length or create text file for update
    • w+x create text file for update
    • a+ append; open or create text file for update, writing at end-of-file
    • r+b or rb+ open binary file for update (reading and writing)
    • w+b or wb+ truncate to zero length or create binary file for update
    • w+bx or wb+x create binary file for update
    • a+b or ab+ append; open or create binary file for update, writing at end-of-file

    271) If the string begins with one of the above sequences, the implementation might choose to ignore the remaining characters, or it might use them to select different kinds of a file (some of which might not conform to the properties in §7.21.2).