Ranj
Ranj

Reputation: 788

How to determine the size of (all the content) a file so I can allocate memory for it at once?

I am trying to allocate memory for the content of a file with words(separated by: \n).

How do I replace the 16000 to make it usable with files of greater size?

My code:

typedef struct node {
    bool is_word;
    struct node* children[27];
} node;

node* root;


bool load(const char* dictionary)
{
    FILE *fp;
    fp = fopen(dictionary, "rb");


    node* node_bucket = calloc(16000, sizeof(node));
    node* next_free_node = node_bucket;

    // compute...

    // to later free the memory with another function
    root = node_bucket;
}

Thanks

Upvotes: 2

Views: 72

Answers (2)

nalzok
nalzok

Reputation: 16107

The simplest approach to get the size of a file is using ftell():

fseek(fp, 0, SEEK_END); // non-portable
long size = ftell(fp);

However, as the comment says, this is not portable, because N1570 documents in "7.21.9.2 The seek function":

2 ...... A binary stream need not meaningfully support fseek calls with a whence value of SEEK_END.

Alternatively, you can write a function to get the size of a file on your own:

size_t fSize(FILE *fp)
{
    void *ptr = malloc(1);
    size_t size = 0;
    while(fread(ptr, 1, 1, fp) == 1)
        size++;
    if(feof(fp))
        return size;
    else
        return 0; // reading error
}

An accuracy-efficiency trade-off:

size_t fRoughSize(FILE *fp)
{
    void *ptr = malloc(1024);
    size_t size = 0;
    while(fread(ptr, 1024, 1, fp) == 1024)
        size += 1024;
    if(feof(fp))
        return size;
    else
        return 0; // reading error
}

Upvotes: 1

Weather Vane
Weather Vane

Reputation: 34585

You can allocate memory dynamically without knowing how large the file is. I used a block size that is a power of 2, which is generally kinder towards block I/O. It wastes a little when the last block is only partially used, but here is an example, which you could adapt to work with your node structs:

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

#define BLOCKSIZE 16384

int main(void) {
    unsigned char *buf = NULL;
    unsigned char *tmp = NULL;
    size_t totalread = 0;
    size_t currentsize = 0;
    size_t currentread = 0;
    FILE *fp;

    if((fp = fopen("test.txt", "rb")) == NULL)
        exit(1);
    do {
        currentsize += BLOCKSIZE;
        if((tmp = realloc(buf, currentsize)) == NULL)
            exit(1);
        buf = tmp;
        currentread = fread( &buf[totalread], 1, BLOCKSIZE, fp);
        totalread += currentread;
    } while (currentread == BLOCKSIZE);

    printf("Total size was %zu\n", totalread);
    free(buf);
    fclose(fp);
    return 0;
}

Upvotes: 2

Related Questions