Search code examples
cfile-iohexfwritexxd

C - fwrite - can't open file because it contains invalid characters


I'm writing an array of 3 integers to a file using C's fwrite function but when opening the output file with gedit (using Unicode UTF-8), I get the following error:

There was a problem opening the file.  The file you opened has invalid characters.  If you continue editing this file, you could corrupt the document.

Here's the relevant code snippet:

char* imageFile = "image.txt";
FILE* imageFilePtr = fopen(imageFile, "w");

int scores[3] = {69, 70, 71};
fwrite(scores, sizeof(int), sizeof(scores), imageFilePtr);

When I use a hexadecimal reader such as "xxd", I get the following in my terminal:

0000000: 4500 0000 4600 0000 4700 0000 7031 7108  E...F...G...p1q.
0000010: 0830 7108 2987 0408 2087 0408 0460 cebf  .0q.)... ....`..
0000020: 0100 0000 0000 0000 0000 0000 0000 0000  ................

Keep in mind that the in my environment, sizeof(int) is 4 bytes. Thus, I can see how 69, 70, and 71 in decimal are being printed to the file as 45, 46, and 47 in hex as xxd shows. But, where are all the other bytes after "4700 0000" coming from? And, why can't I open the output file, "image.txt", with a text editor to see a file that shows the decimal numbers, 69, 70, and 71 written inside?


Solution

  • There are two problems I can see here. One is that you are trying to open a binary file in a text editor. The second is that you have a buffer read overflow when writing the binary file. I'll address the second one first.

    the fwrite function takes a "size of element" and a "count of elements" as parameters. You have put the size of element as sizeof(int) which is correct, however for the count you have done sizeof(scores) which is actually 3*sizeof(int), whereas you actually need the value 3. Assuming int size is 4 (32bit) then the count value is being set at 12. Which means it is trying to write 48 bytes to the file instead of 12. The additionally 36 bytes is a read overflow on the stack.

    To get the number of elements in array you can use: sizeof(scores)/sizeof(scores[0]).

    fwrite(scores, sizeof(int), sizeof(scores)/sizeof(scores[0]), imageFilePtr);
    

    I would use a macro for this so I could go

    fwrite(scores, sizeof(int), NumOfElements(scores), imageFilePtr);
    

    where NumOfElements is defined as:

    #define NumOfElements(Array) (sizeof(Array)/sizeof(Array[0]))
    

    Now for the first problem. I believe you were trying to write 3 integers into a text file. The fwrite function writes binary data. What you want to use is fprintf. This works the same way as printf but will let you write to a file. However you can not write an array of numbers with one fprintf, so you would have to have a loop.

    for( i=0; i<NumOfElements(scores); i++ )
    {
        fprintf( imageFilePtr, "%u\n", scores[i] );
    }
    

    This will write each number into the file on a seperate line.