Search code examples
cfilepointersfopenbmp

why would fopenf_s initialize the file pointer to be NULL when working with bmp file in C?


I'm trying to write to an existing bmp file. the action should delete the data on it, which is fine by me. first i want to read the original header, then switch the width and the height data and then "create" new file with the new header. for some reason, i managed to open and read the file in "rb" mode, but when i try to do so in "wb" mode or any other mode for writing, the file pointer is initialized as NULL.

reading with struct BmpHeader works just fine.

Update: after using:

   err = fopens(...);

i got that err = 13. how can i fix this?

#define HEADERSIZE 54

int **Matrix = GivenMatrix;
    FILE *f;
    int row, col,i;
    BmpHeader header;
    long  Newwidth, Newheight;
    int pixelBytesInRow, padding;


    fopen_s(&f, "plate.bmp", "rb");
    fread(&header, HEADERSIZE, 1, f);
    fclose(f);
    Newheight = header.width;
    Newwidth = header.height;
    header.width = Newwidth;
    header.height = Newheight;

    fopen_s(&f, "plate.bmp", "wb");

    fwrite(&header, HEADERSIZE, 1, f);


Solution

  • fopen_s() returns a non-zero error code and sets the file handle to null and the global value errno to the appropriate error code when an error occurs. To see what happened, use perror() to print the error message:

    if (fopen_s(&f, "plate.bmp", "wb") != 0) {
        perror("could not open plate.bmp");
    
        // Exit or return.
    }
    

    perror() will append the system's error to your own message, with a : before it.

    Also do the same when opening the file for reading. Never assume that file operations are going to succeed. You really, really need to do error handling when doing any kind of I/O.

    If the error is "permission denied", then that usually means the file is open elsewhere. Either in your own program, or by an external program (like an image viewer you're using to check the bmp file.) Close it. On Windows, you can't open files in write mode if they are open elsewhere too.

    If you want to avoid situations where you forgot to close files, you should use RAII facilities in C++. It's arguably the most important and useful part of C++. In this case, you could either switch to C++ streams, or if you want to continue using the cstdio API, then wrap your file handles in your own type that automatically closes the handle when it goes out of scope (either in the destructor, or by using a unique_ptr with a the custom deleter set to fclose.)