File Handling

Opening, reading from, writing to, and closing files in C. Using functions like `fopen`, `fclose`, `fread`, `fwrite`, `fprintf`, and `fscanf`.


Working with Text Files in C

Introduction

C programming provides powerful mechanisms for interacting with files, including reading from and writing to text files. This allows you to store and retrieve data persistently. Text files are particularly useful for storing configuration settings, log files, and other human-readable data.

Understanding File Pointers

In C, file operations are performed using file pointers. A file pointer is a variable of type FILE* that points to a file structure. This structure contains information about the file, such as its current position, status, and buffering.

To work with a file, you need to:

  1. Declare a file pointer (FILE *fp;).
  2. Open the file using fopen(), associating the file with the file pointer.
  3. Perform operations on the file (read/write).
  4. Close the file using fclose() when you are finished.

Opening and Closing Files

The fopen() function is used to open a file. It takes two arguments: the file name (string) and the mode (string). The mode specifies how the file is to be opened (e.g., read, write, append). The function returns a file pointer if successful, or NULL if an error occurs.

Common modes:

  • "r": Read mode (file must exist).
  • "w": Write mode (creates a new file or overwrites an existing one).
  • "a": Append mode (writes to the end of the file, creating it if it doesn't exist).
  • "r+": Read and write mode (file must exist).
  • "w+": Read and write mode (creates a new file or overwrites an existing one).
  • "a+": Read and append mode (opens for reading and appending).

The fclose() function closes a file associated with a file pointer. It's crucial to close files to free up system resources and ensure that any buffered data is written to the file.

Reading from Text Files

There are several functions available for reading data from text files:

  • fgetc(): Reads a single character from the file.
  • fgets(): Reads a line of text from the file.
  • fscanf(): Reads formatted data from the file. Similar to scanf() but reads from a file.

Example: Reading a Single Character

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

int main() {
    FILE *fp;
    char ch;

    fp = fopen("example.txt", "r");

    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    ch = fgetc(fp);

    if (ch != EOF) {
        printf("Character read: %c\n", ch);
    } else {
        printf("End of file reached or error.\n");
    }

    fclose(fp);
    return 0;
} 

Example: Reading a Line of Text

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

int main() {
    FILE *fp;
    char line[100];

    fp = fopen("example.txt", "r");

    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    if (fgets(line, sizeof(line), fp) != NULL) {
        printf("Line read: %s", line);  // fgets includes the newline character
    } else {
        printf("End of file reached or error.\n");
    }

    fclose(fp);
    return 0;
} 

Example: Reading Formatted Data

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

int main() {
    FILE *fp;
    char name[50];
    int age;

    fp = fopen("data.txt", "r"); // Assumes data.txt contains "John 30"

    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    if (fscanf(fp, "%s %d", name, &age) == 2) {
        printf("Name: %s, Age: %d\n", name, age);
    } else {
        printf("Error reading data from file.\n");
    }

    fclose(fp);
    return 0;
} 

Writing to Text Files

Similar to reading, several functions are available for writing data to text files:

  • fputc(): Writes a single character to the file.
  • fputs(): Writes a string to the file.
  • fprintf(): Writes formatted data to the file. Similar to printf() but writes to a file.

Example: Writing a Single Character

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

int main() {
    FILE *fp;

    fp = fopen("output.txt", "w");

    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    fputc('A', fp);

    fclose(fp);
    printf("Character written to file.\n");
    return 0;
} 

Example: Writing a String

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

int main() {
    FILE *fp;

    fp = fopen("output.txt", "w");

    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    fputs("Hello, world!\n", fp);

    fclose(fp);
    printf("String written to file.\n");
    return 0;
} 

Example: Writing Formatted Output

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

int main() {
    FILE *fp;
    char name[] = "Alice";
    int age = 25;

    fp = fopen("output.txt", "w");

    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    fprintf(fp, "Name: %s, Age: %d\n", name, age);

    fclose(fp);
    printf("Formatted output written to file.\n");
    return 0;
} 

Common Text File Processing Tasks

Here are some common tasks you can perform using text files in C:

  • Counting Lines, Words, and Characters: Iterate through the file, incrementing counters for each line, word, or character. Use fgetc() to read characters, check for newline characters to count lines, and split text by spaces to count words.
  • Searching for a Specific String: Read the file line by line using fgets() and use strstr() (from string.h) to search for the string within each line.
  • Replacing Strings: Read the file line by line. If a line contains the string to be replaced, create a new string with the replacement using strstr() and string manipulation functions like strncpy() and strcat(). Write the modified line to a temporary file. After processing all lines, replace the original file with the temporary file. This is more complex and requires careful handling of file pointers and temporary storage.
  • Sorting Lines in a File: Read all the lines from the file into an array of strings. Use a sorting algorithm (e.g., bubble sort, quicksort) to sort the array of strings. Then, write the sorted lines back to the file (or a new file).
  • Concatenating Files: Open multiple files in read mode and a destination file in write mode. Read from each source file line by line using fgets() and write each line to the destination file using fputs().

Error Handling

It's crucial to handle potential errors when working with files. The fopen() function can return NULL if it fails to open a file. The perror() function (from stdio.h) can be used to print a descriptive error message to the standard error stream. Always check the return values of file operations to ensure they were successful.

Example of error handling:

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

int main() {
    FILE *fp;

    fp = fopen("nonexistent_file.txt", "r");

    if (fp == NULL) {
        perror("Error opening file");
        return 1; // Exit with an error code
    }

    // ... rest of your file operations ...

    fclose(fp);
    return 0;
}