Course Topics
C Basics Introduction and Setup Syntax and Program Structure Comments and Documentation Compiling and Running C Programs Exercise Variables and Data Types Variables and Declaration Data Types (int, float, char, double) Constants and Literals Type Conversion and Casting Exercise Operators Arithmetic Operators Comparison Operators Logical Operators Assignment Operators Bitwise Operators Exercise Input and Output Standard Input/Output (scanf, printf) Format Specifiers File Input/Output Exercise Control Flow - Conditionals If Statements If-Else Statements Switch Statements Nested Conditionals Exercise Control Flow - Loops For Loops While Loops Do-While Loops Loop Control (break, continue) Nested Loops Exercise Functions Defining Functions Function Parameters and Arguments Return Statements Scope and Variables Recursion Exercise Arrays One-Dimensional Arrays Multi-Dimensional Arrays Array Operations Strings as Character Arrays Exercise Pointers Introduction to Pointers Pointer Arithmetic Pointers and Arrays Pointers and Functions Dynamic Memory Allocation Exercise Strings String Handling String Functions (strlen, strcpy, strcmp) String Manipulation Exercise Structures Defining Structures Structure Members Arrays of Structures Pointers to Structures Exercise File Handling Opening and Closing Files Reading from Files Writing to Files File Positioning Exercise Memory Management Static vs Dynamic Memory malloc() and free() Memory Leaks Best Practices Exercise Advanced Topics Preprocessor Directives Macros Header Files Modular Programming Exercise Final Project Project Planning Building Complete Application Code Organization Testing and Debugging Exercise

File Input/Output

Introduction

File Input/Output (I/O) is a fundamental concept in programming that allows you to read data from and write data to files on your computer. This topic matters because it enables you to work with external data sources, such as text files or databases, which can be crucial for a wide variety of applications like data analysis, system configuration, and web development. By the end of this lesson, you'll learn how to perform basic file I/O operations using C language.

Core Concepts

File Stream

In C, files are treated as streams of bytes. A file stream is an abstract representation of a file, which allows us to read from or write to the file using standard I/O functions.

Opening a File

To work with a file in C, you must first open it by creating a file stream associated with that file. This is done using the fopen() function:

FILE *file_stream = fopen("filename", "mode");

Here, "filename" specifies the name of the file to be opened, and "mode" defines how the file should be opened. The possible modes are as follows:

  • "r" : Open a file for reading (default behavior).
  • "w" : Open a file for writing. If the file already exists, its contents will be destroyed.
  • "a" : Open a file for appending. If the file does not exist, it will be created.
  • "r+": Open a file for both reading and writing (update mode).
  • "w+": Open a file for both reading and writing (truncate mode).
  • "a+" : Open a file for both reading and appending.

Reading Data from a File

To read data from a file, you can use the fgets() function or the fscanf() function.

char line[100];
int num;

// Using fgets
if (fgets(line, sizeof(line), file_stream) != NULL) {
  printf("Read data: %s", line);
}

// Using fscanf
if (fscanf(file_stream, "%d", &num) == 1) {
  printf("Read number: %d", num);
}

Writing Data to a File

To write data to a file, you can use the fprintf() function.

if (fprintf(file_stream, "Hello, World!\n") > 0) {
  printf("Wrote data successfully.");
}

Closing a File

After you're done working with a file, it is essential to close the associated file stream using the fclose() function.

if (fclose(file_stream) == 0) {
  printf("Closed file successfully.");
}

Practical Examples

Reading a Text File Line by Line

Let's read a text file named "data.txt" line by line and print its contents:

#include <stdio.h>

int main() {
  FILE *file = fopen("data.txt", "r");
  char line[100];

  if (file != NULL) {
    while (fgets(line, sizeof(line), file) != NULL) {
      printf("%s", line);
    }

    if (fclose(file) == 0) {
      printf("File closed successfully.");
    }
  } else {
    printf("Could not open the file.");
  }

  return 0;
}

Writing Data to a File

Let's create and write data to a new text file named "output.txt":

#include <stdio.h>

int main() {
  FILE *file = fopen("output.txt", "w");
  if (file != NULL) {
    fprintf(file, "Hello\nWorld\n!");

    if (fclose(file) == 0) {
      printf("File closed successfully.");
    }
  } else {
    printf("Could not open the file.");
  }

  return 0;
}

Common Issues and Solutions

NameError: FILE is not declared (the type 'FILE' is undefined)

What causes it: This error occurs when you haven't included the necessary header file stdio.h.

Solution: Include the following line at the beginning of your code to resolve this issue:

#include <stdio.h>

TypeError: incompatible types when using fscanf()

What causes it: This error occurs when you're trying to read data into a variable of the wrong type. For example, reading an integer into a character array.

Solution: Make sure that the format specifier and the target variable match when using fscanf().

SyntaxError: semicolon expected after control statement

What causes it: This error occurs when you forget to put a semicolon (;) at the end of a control statement like if, while, or for.

Solution: Add a semicolon at the end of each control statement.

FileNotFoundError: No such file or directory

What causes it: This error occurs when you try to open a non-existent file or specify an incorrect file path.

Solution: Ensure that the file exists and the provided file path is correct. If necessary, create the file before trying to open it.

RuntimeError: fopen() returned NULL (cannot open file)

What causes it: This error occurs when there's an issue with opening the file, such as insufficient permissions or an incorrect mode specified for opening the file.

Solution: Check that you have the necessary permissions to read/write the file and ensure that the provided mode for fopen() is appropriate for your use case.

Best Practices

  • Use meaningful and descriptive names for your files.
  • Always close the file stream after finishing with it to free up system resources.
  • Be cautious when reading user input from files, as it may contain malicious content or unexpected data.
  • When writing data to a file, ensure that the file is opened in the appropriate mode and that you have permission to write to the specified location.

Key Takeaways

  • Files are treated as streams of bytes in C.
  • Use fopen() to open files in various modes for reading or writing.
  • Read data from a file using fgets(), fscanf(), or similar functions.
  • Write data to a file using fprintf().
  • Always close the file stream with fclose().
  • Be mindful of common issues when working with files and follow best practices for optimal results.