Search code examples
cftell

Why the ftell returns 0 in this function?


When I run my program and I choose to see the product list, it doesn't print anything. After some time, I find out that the value of fl_size is always 0. Why is this?

void view_prdct_code_list() {
        FILE *stock = fopen("stock.dat","r+");
        assert(stock);

        int fl_size=ftell(stock);
        int prd_size= sizeof(product);
        int quantity= fl_size/prd_size;
        printf("fl_size=%d",fl_size);

        fseek(stock,0,SEEK_SET);
        prdct cprd= (product *)malloc (sizeof(product)*quantity);
        assert(cprd);

        int i;

        fread(cprd,prd_size,quantity,stock);

        for (i=0;i<quantity;i++){
                printf("PRODUCT CODE: %d\n",cprd->code);
        }

        free(cprd);
        fclose(stock);
}

Solution

  • ftell does not return the total size of the file; it returns the current read or write position within the file. You call ftell immediately after opening the file, so that position is the very beginning of the file. You can either use fseek(stock, 0, SEEK_END) to seek to the end before calling ftell, or you can drop down a layer and use fstat(fileno(stock)) to retrieve the file size directly from the OS.

    Further notes:

    1. Neither of these options will work if you are reading from a pipe. (In general, you need to check for the success of every single one of your file access operations.)
    2. fread is not guaranteed to read the entire file in one gulp even if you ask it to.
    3. As 'alk' points out, ftell returns a long, not an int.
    4. If long is only 32 bits, it is possible for a file to be so large that its size does not fit in a long. If your program needs to handle files that big, you need to #define _FILE_OFFSET_BITS 64 at the top of every .c file (before all the includes) and use fseeko and ftello. (Or whatever the Windows equivalent is.)
    5. You should be opening this apparently-binary file with mode "r+b".
    6. Binary files with no file header (and in particular with no magic number, of at least four bytes, at offset zero) are a Bad Thing.
    7. Do not cast the return value of malloc. (It is necessary to do this in C++, but in C it is not only unnecessary, it can hide bugs.)