Veronica Veronica - 2 months ago 18
C Question

fread or fwrite gives "Bad file number"

I am using MinGW in Windows 8.1 and I have an input text file of raw numbers (one per line) and I want to write them as binary in a new binary file. The example is compiling without problems with:

gcc -pedantic -Os -c my_code.c -o my_code.exe


but the output is

$ my_code.exe
sh: ./my_code.exe: Bad file number


This is the code I wrote:

#include<stdio.h>

int main ()
{
FILE *fp;
FILE *prob;
int length;
char buffer[30];

// Open file containing numbers
if ((prob = fopen("raw_numbers.txt","r")) == NULL)
{
printf("Could not open raw_numbers.txt\n");
exit(1);
}

/* Create output binary file */
fp = fopen( "file.bin" , "w" );

while( ! feof(prob) )
{
fgets(buffer, sizeof(buffer), prob);
fwrite((const void*) & buffer, 1, sizeof(buffer), fp);
}

fclose(prob);
fclose(fp);
return(0);
}


Using

$ gcc --version
gcc (GCC) 3.4.4 (msys special)

Answer

You have multiple errors in your program:

  • you should test for failure to create the output file.

  • you should test the return value of fgets() instead of using while (!feof())..., which does not do what you think as explained in Why is “while ( !feof (file) )” always wrong?

  • you should pass buffer to fwrite instead of &buffer

  • you should pass the number of bytes to write (strlen(buffer)) instead of the size of the buffer.

  • you say the output file should be binary, but you open it as a text file and write text to it. Did you mean to convert the numbers to binary and write the binary representation?

Here is an alternative that implements the above:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *fp;
    FILE *prob;
    int value;
    char buffer[30];

    /* Open file containing numbers */
    if ((prob = fopen("raw_numbers.txt", "r")) == NULL) {
        printf("Could not open raw_numbers.txt: %s\n", strerror(errno));
        exit(1);
    }

    /* Create output binary file */
    if ((fp = fopen("file.bin", "wb")) == NULL) {
        printf("Could not open file.bin: %s\n", strerror(errno));
        exit(1);
    }

    while (fgets(buffer, sizeof(buffer), prob) != NULL) {
        value = atoi(buffer);
        if (fwrite(&value, sizeof(value), 1, fp) != 1) {
            printf("Error writing to file.bin: %s\n", strerror(errno));
            exit(1);
        }
    }

    fclose(prob);
    fclose(fp);
    return 0;
}

The shell diagnostic is misleading, but here is what it means: the file my_code.exe has a signature (also known as magic number) that is not recognized as an executable file. The kernel cannot determine how to run the file from its magic number, hence Bad file number.

The reason is your compilation command: gcc -pedantic -Os -c my_code.c -o my_code.exe compiles the source file my_code.c to object format instead of linking directly to executable format. Remove the -c option to compile and link in one step:

gcc -pedantic -Os my_code.c -o my_code.exe
Comments