Read a Text File Line by Line in C

By | 2021-10-17

If you are like me and spend most of your time on Linux or UNIX systems, you deal with text files a lot. I recently encountered a situation requiring that I read a text file line by line in C.

The most straightforward way to read a text file line by line in C is the getline function. On my Debian and FreeBSD systems, the prototype can be found in stdio.h and shared object code can be found in libc.so. According to the man page on my Debian system, getline is part of POSIX.1-2008. Since it is a POSIX standard, I would assume it is available in any UNIX like C implementation, but I am not certain. I haven’t tried this on Windows implementations either.

ssize_t getline(char **lineptr, size_t *n, FILE *stream);

The above prototype is taken from the Linux man page, so if you are on another system, it will look slightly different.

Each call fills a heap allocated buffer with a line of text, terminated by null. On a successful call, it returns the length of the line, not including the terminating null character. This includes the new line. It returns -1 if it reaches the end of the file or encounters an error. E.g. if a line is Hello\n (\n is a newline character), the return value would be 6 and lineptr would point to a 6 character string Hello followed by a new line and a null.

You can use getline in two ways. One is to let it allocate the buffer it stores the lines in. The other is to allocate it yourself. With the second option, if getline needs more memory, it will allocate more for you.

The table describes the arguments:

ARGUMENT DESCRIPTION
char **lineptr A pointer to the buffer containing the string. It is null terminated, so it is safe to use string functions that depend on null termination.
size_t *n The size of the buffer *lineptr points to. This is NOT the size of the string. Remember, the size of the string is the return value. getline will set this for you if it allocates the buffer for you.
FILE *stream A file pointer of an open file you wish to read.

Below is an example program that prints the line number, length of the line, and finally the line itself of an input file.

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

int main(int argc, char *argv[]) {
    
    FILE            *f;
    size_t          len;
    size_t          buffer_size;
    char            *line;
    unsigned int    i;

    line         = NULL;
    buffer_size  = 0;

    if( argc != 2) {
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        return 1; }

    if( NULL == (f = fopen(argv[1], "r"))) {
        fprintf(stderr, "Could not open %s\n", argv[1]);
        perror("Error: ");
        return 1; }

    for(i=1; -1  != (len = getline(&line, &buffer_size, f));i++ ) 
        printf("%4u: %4lu %s", i, len, line);

    free(line);
    fclose(f);

    return 0;

}

First, it sets the buffer pointer and buffer length to NULL so getline will take care of memory allocation for us. Next, it checks to see if it has one and only one argument, printing a usage message if it doesn’t. Then it opens the file, outputting an error message if it is unable to. Now it is able to loop through file with getline calls in a for loop. Last, it frees the memory allocated by getline and closes the file.

If you are interested in a more in depth exploration of this topic, The Solarian Programmer covers it very well.

References

See Also