Ways to get the file size in C
Tags: cprogramming, filehandling, programming, operatingsystem
Published: 2022-07-16 19:27:00

In this article, I will discuss two approaches for getting the file size using the C programming language.


### Approach 1

When we have to get the file size first approach that comes to our mind is to open the file, _seek_ the _cursor_ to the end of the file, and then get the position of the _cursor_ which is nothing but the size of the file.

Let's understand how can we achieve this.

- First, open a file using `fopen`. The first argument is the file path and the second argument is `mode` and it returns the `file descriptor`. Since we don't have to modify the file open it in _read_ mode using `"r"`.
- Now move the _cursor_ to the end of the file using `fseek` which takes the following arguments respectively.
  - `fd` file descriptor of the file opened.
  - `offset` how much to offset w.r.t the third argument position.
  - `whence` from where the cursor should consider moving from. 
  We have three options for it, `SEEK_SET` relative to the start of the file, `SEEK_CUR` relative to the current position, and `SEEK_END` relative to the end of the file.

Since we have to move to the end of the file we take relative to the end of the file and offset it as zero, as we have to move zero from the end. `fseek` return `-1` if it fails.
- Now use `ftell` to get the current position which takes `fd` as an argument and returns the current position which is our file size. On failing it returns `-1`.

> **NOTE**: If the cursor move by 1 unit we consider it as 1 byte because the size of `char` is 1 byte and `fopen` reads the file character by character only.

**Code**

```c
#include <stdio.h>

// function get file size
long get_file_size(char *);

int main() {
    char *filename = "a.out";
    printf(
        "Size of file `%s` is %ld\n", 
        filename, 
        get_file_size(filename)
    );

    return 0;
}

long get_file_size(char *filename) {
    FILE *fp = fopen(filename, "r");

    if (fp==NULL)
        return -1;

    if (fseek(fp, 0, SEEK_END) < 0) {
        fclose(fp);
        return -1;
    }

    long size = ftell(fp);
    // release the resources when not required
    fclose(fp);
    return size;
}
```

**Output**

```bash
Size of file `a.out` is 51880 bytes
```

### Approach 2
In this approach, we use `stat` API to get the file information which also includes _file size_.
For this, we simply call the `stat` function which takes a _file path_ as the first argument and pointer to the _stat struct_ variable as the second argument and returns `-1` on failure.

To get the file size we can simply use the `st_size` attribute. 

**Code**

```c
#include <sys/stat.h> // stat

// inherit the above base code here

long get_file_size(char *filename) {
    struct stat file_status;
    if (stat(filename, &file_status) < 0) {
        return -1;
    }

    return file_status.st_size;
}
```

**Output**

```bash
Size of file `a.out` is 51880 bytes
```

Using this we can get some other information about a file such as permission, creation time, user id, group id, etc. Also, there are some other functions defined that can be used based on requirements. Check out its [man page](https://man7.org/linux/man-pages/man2/lstat.2.html) for more info.

### Which one should be used?

The second approach is more recommended because of the following reason.

- It's fast as we don't have to open a file which in the first approach has to be done. Some compilers may buffer a file on opening which makes the first approach slower.
- The code is more clear to other developers that we are trying to get file info.

But this code is not portable. As other APIs are developed on OS like windows to get file info.

Whereas the first approach code is portable. As same code works normally without any problem.

So, in conclusion, which strategy we should take is entirely dependent on our requirements.

---

> This article is highly inspired by the content provided by **Jacob Sorber** on his [youtube channel](https://www.youtube.com/c/JacobSorber).

❤️Thank you so much for reading this article. I'm a passionate engineering student learning new things so If you find any mistakes or have any suggestions please let me know in the comments.

Also, consider sharing and giving a thumbs up If this post helps you in any way.