Read File Line By Line C

5 min read

Reading a file line by line in C is a fundamental skill for any programmer who needs to process text data efficiently. Whether you are parsing configuration files, analyzing log outputs, or implementing simple text‑based utilities, knowing how to safely and reliably extract each line from a file stream is essential. This guide walks you through the most common techniques, explains the underlying mechanics, and provides practical examples that you can adapt to your own projects.

Why Read a File Line by Line?

Processing a file sequentially, one line at a time, offers several advantages over loading the entire contents into memory:

  • Memory efficiency – Large files (megabytes or gigabytes) can be handled without allocating huge buffers.
  • Simplicity – Algorithms that naturally operate on lines (e.g., searching for a pattern, counting words) become straightforward.
  • Early termination – You can stop reading as soon as a condition is met, saving I/O time.
  • Streaming compatibility – Works with pipes, sockets, or any source that presents data as a stream.

Understanding these benefits helps you decide when a line‑by‑line approach is preferable to alternatives like mmap or reading the whole file into a buffer And that's really what it comes down to. No workaround needed..

Core Functions for Line‑by‑Line Reading

C’s standard library provides two primary ways to fetch a line from a FILE* stream:

Function Description Typical Use
char *fgets(char *s, int size, FILE *stream) Reads up to size‑1 characters or until a newline (\n) or EOF, storing the result in the buffer s. Returns the number of characters read (including the newline) or -1 on error/EOF. Consider this: Portable, works on all C implementations.
ssize_t getline(char **lineptr, size_t *n, FILE *stream) Dynamically allocates or reallocates a buffer to hold the entire line, updating *lineptr and *n. Practically speaking, the newline is kept if it fits. Convenient when line length is unknown or may exceed a fixed limit.

Both functions set the stream’s error and EOF flags appropriately, allowing you to detect problems after each call.

Using fgets

fgets is the classic, universally available method. And you must supply a buffer large enough for the longest line you expect, plus one byte for the terminating null character. But if a line exceeds the buffer size, fgets will read the first size‑1 characters, leave the newline (if present) in the stream, and return the partially filled buffer on the next call. This behavior requires careful handling when you need to guarantee that you have obtained a complete line Most people skip this — try not to..

Real talk — this step gets skipped all the time.

Using getline

Introduced in POSIX.Subsequent calls reuse or grow the buffer as needed. Because of that, on the first call, you can set *lineptr to NULL and *n to 0; getline will allocate memory using malloc. You pass the address of a pointer to a buffer (char **lineptr) and the address of a size variable (size_t *n). On the flip side, 1‑2008, getline simplifies line reading by managing memory for you. Remember to free the allocated buffer when you are done.

Step‑by‑Step Example: Reading a File with fgets

Below is a complete, self‑contained program that opens a text file named input.Also, txt, reads it line by line using fgets, and prints each line with its line number. Error checking is performed after each library call.

#include 
#include 

#define BUFFER_SIZE 1024   /* Adjust according to expected line length */

int main(void) {
    FILE *fp = fopen("input.txt", "r");
    if (fp == NULL) {
        perror("Failed to open file");
        return EXIT_FAILURE;
    }

    char buffer[BUFFER_SIZE];
    unsigned long line_num = 0;

    while (fgets(buffer, sizeof buffer, fp) != NULL) {
        ++line_num;
        /* Optionally strip the trailing newline */
        size_t len = strlen(buffer);
        if (len > 0 && buffer[len - 1] == '\n')
            buffer[len - 1] = '\0';

        printf("%lu: %s\n", line_num, buffer);
    }

    if (ferror(fp)) {
        perror("Error while reading file");
        fclose(fp);
        return EXIT_FAILURE;
    }

    fclose(fp);
    return EXIT_SUCCESS;
}

Explanation of key parts

  • fopen opens the file for reading ("r"). If it returns NULL, we use perror to display a system‑provided error message.
  • The while loop continues as long as fgets returns a non‑NULL pointer, indicating that characters were successfully read.
  • After each successful read, we increment line_num and optionally remove the newline character so that printf does not add an extra blank line.
  • After the loop, we test ferror to distinguish between a normal EOF and an actual read error.
  • Finally, we close the file with fclose to release system resources.

Step‑by‑Step Example: Reading a File with getline

The same task using getline looks noticeably shorter because memory management is handled automatically:

#include 
#include 

int main(void) {
    FILE *fp = fopen("input.txt", "r");
    if (fp == NULL) {
        perror("Failed to open file");
        return EXIT_FAILURE;
    }

    char *line = NULL;
    size_t len = 0;
    ssize_t read;
    unsigned long line_num = 0;

    while ((read = getline(&line, &len, fp)) != -1) {
        ++line_num;
        if (read > 0 && line[read - 1] == '\n')
            line[read - 1] = '\0';   /* strip newline */

        printf("%lu: %s\n", line_num, line);
    }

    if (ferror(fp)) {
        perror("Error while reading file");
        free(line);
        fclose(fp);
        return EXIT_FAILURE;
    }

    free(line);   /* release the buffer allocated by getline */
    fclose(fp);
    return EXIT_SUCCESS;
}

Key points

  • line starts as NULL and len as 0; getline allocates memory on the first call.
  • The return value read is the number of characters stored, including the newline if present. A return of -1 signals EOF or error.
  • After processing, we explicitly free(line) to avoid a memory leak.
  • Error handling mirrors the fgets version: we check ferror after the loop.

Error Handling and Robustness

reliable file I/O anticipates a variety of failure modes:

  1. File not found or permission issues – Check the return value of fopen and use perror or strerror(errno) to diagnose.
  2. **Read errors mid‑
Newest Stuff

Just Finished

Connecting Reads

Before You Head Out

Thank you for reading about Read File Line By Line C. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home