C Language File Operations: A Comprehensive Guide

Data Persistence Through File Operations

Program data stored in memory is lost when the application terminates. To preserve information between sessions, file storage mechanisms are essential.

File Classification

Program vs Data Files

Software projects involve two primary file categories:

Program Files encompass:

  • Source code files (.c extension)
  • Compiled object files (.obj in Windows)
  • Executable binaries (.exe in Windows)

Data Files contain runtime information that programs read or write during execution, distinct from executable code.

File Identification

Each file requires a unique identifier consisting of:

  • Directory path
  • Base filename
  • Extension

Example: c:\projects\sample.txt

Text vs Binary Storage Formats

Data orgenization determines file classification:

Binary Files store raw memory representations without conversion.

Text Files encode data using ASCII characters, requiring transformation before storage.

Numeric values demonstrate the difference:

  • Integer 10000 as ASCII text requires 5 bytes (one per digit)
  • Same integer in binary format uses only 4 bytes
#include <stdio.h>

int main() {
    int value = 10000;
    FILE* output = fopen("example.dat", "wb");
    fwrite(&value, sizeof(int), 1, output);
    fclose(output);
    return 0;
}

Stream Management and File Pointers

Standard Streams

C programs automatically initialize three streams:

  • stdin for kyeboard input (scanf source)
  • stdout for display output (printf destination)
  • stderr for error messages

These streams use FILE* type variables for internal management.

File Pointer Structure

The FILE structure maintains file state information including:

  • Current position
  • Buffer status
  • File attributes
struct file_control {
    char* buffer_ptr;
    int available_chars;
    char* base_address;
    int flags;
    int file_descriptor;
    int char_buffer;
    int buffer_size;
    char* temp_filename;
};

typedef struct file_control FILE;

Opening and Closing Files

ANSI C provides standardized functions:

FILE* fopen(const char* filename, const char* mode);
int fclose(FILE* stream);

Available modes include:

  • "r" Read-only
  • "w" Write (truncates existing)
  • "a" Append
  • "rb" Binary read
  • "wb" Binary write
int main() {
    FILE* data_file = fopen("records.txt", "w");
    if (data_file == NULL) {
        perror("File creation failed");
        return 1;
    }
    fclose(data_file);
    data_file = NULL;
    return 0;
}

Sequential File Access Methods

Character Operatoins

Writing Characters

#include <stdio.h>

int main() {
    FILE* target = fopen("alphabet.txt", "w");
    if (target == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    for (int idx = 0; idx < 26; idx++) {
        fputc('a' + idx, target);
    }
    
    fclose(target);
    target = NULL;
    return 0;
}

Reading Characters

int main() {
    FILE* source = fopen("alphabet.txt", "r");
    if (source == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    int character;
    while ((character = fgetc(source)) != EOF) {
        putchar(character);
    }
    
    fclose(source);
    source = NULL;
    return 0;
}

String Operations

Writing Lines

int main() {
    FILE* document = fopen("lines.txt", "w");
    if (document == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    fputs("First line\n", document);
    fputs("Second line\n", document);
    
    fclose(document);
    document = NULL;
    return 0;
}

Reading Lines

int main() {
    FILE* input = fopen("lines.txt", "r");
    if (input == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    char buffer[100];
    while (fgets(buffer, sizeof(buffer), input) != NULL) {
        printf("%s", buffer);
    }
    
    fclose(input);
    input = NULL;
    return 0;
}

Formatted Operations

Structured Data Writing

#include <stdio.h>

struct student_record {
    char full_name[30];
    int academic_year;
    float gpa;
};

int main() {
    struct student_record student = {"John Smith", 2, 3.75f};
    FILE* records = fopen("students.txt", "w");
    if (records == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    fprintf(records, "%s %d %.2f", 
            student.full_name, 
            student.academic_year, 
            student.gpa);
    
    fclose(records);
    records = NULL;
    return 0;
}

Structured Data Reading

int main() {
    struct student_record retrieved = {0};
    FILE* records = fopen("students.txt", "r");
    if (records == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    fscanf(records, "%s %d %f", 
           retrieved.full_name, 
           &retrieved.academic_year, 
           &retrieved.gpa);
    
    fclose(records);
    records = NULL;
    return 0;
}

Binary Operations

Binary Writing

int main() {
    struct student_record student = {"Alice Johnson", 3, 3.9f};
    FILE* binary_file = fopen("student_data.bin", "wb");
    if (binary_file == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    fwrite(&student, sizeof(student), 1, binary_file);
    
    fclose(binary_file);
    binary_file = NULL;
    return 0;
}

Binary Reading

int main() {
    struct student_record loaded = {0};
    FILE* binary_file = fopen("student_data.bin", "rb");
    if (binary_file == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    fread(&loaded, sizeof(loaded), 1, binary_file);
    printf("%s %d %.1f\n", 
           loaded.full_name, 
           loaded.academic_year, 
           loaded.gpa);
    
    fclose(binary_file);
    binary_file = NULL;
    return 0;
}

String Formatting Functions

Data to String Conversion

int main() {
    struct student_record person = {"Bob Wilson", 1, 3.2f};
    char formatted[100] = {0};
    
    sprintf(formatted, "%s|%d|%.1f", 
            person.full_name, 
            person.academic_year, 
            person.gpa);
    printf("%s\n", formatted);
    
    return 0;
}

String to Data Conversion

int main() {
    struct student_record parsed = {0};
    char source[] = "Carol Brown|4|3.8";
    
    sscanf(source, "%[^|]|%d|%f", 
           parsed.full_name, 
           &parsed.academic_year, 
           &parsed.gpa);
    
    return 0;
}

Random Access Operations

Position Control

#include <stdio.h>

int main() {
    FILE* file_handle = fopen("sample.txt", "r");
    if (file_handle == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    // Read first four characters
    for (int i = 0; i < 4; i++) {
        putchar(fgetc(file_handle));
    }
    
    // Move to position relative to end
    fseek(file_handle, -6, SEEK_END);
    putchar(fgetc(file_handle));
    
    fclose(file_handle);
    file_handle = NULL;
    return 0;
}

Position Tracking

int main() {
    FILE* tracker = fopen("sample.txt", "r");
    if (tracker == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    // Advance cursor
    for (int i = 0; i < 4; i++) {
        fgetc(tracker);
    }
    
    long position = ftell(tracker);
    printf("Current offset: %ld\n", position);
    
    fclose(tracker);
    tracker = NULL;
    return 0;
}

Reset Position

int main() {
    FILE* reset_file = fopen("sample.txt", "r");
    if (reset_file == NULL) {
        perror("Opening failed");
        return 1;
    }
    
    // Read initial characters
    for (int i = 0; i < 4; i++) {
        putchar(fgetc(reset_file));
    }
    
    // Return to beginning
    rewind(reset_file);
    putchar(fgetc(reset_file));
    
    fclose(reset_file);
    reset_file = NULL;
    return 0;
}

End-of-File Detection

Text File Reading

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

int main() {
    int ch;
    FILE* input_file = fopen("content.txt", "r");
    if (!input_file) {
        perror("Opening failed");
        return EXIT_FAILURE;
    }
    
    while ((ch = fgetc(input_file)) != EOF) {
        putchar(ch);
    }
    
    if (ferror(input_file)) {
        puts("Read error occurred");
    } else if (feof(input_file)) {
        puts("End of file reached");
    }
    
    fclose(input_file);
    input_file = NULL;
    return 0;
}

Binary File Reading

int main() {
    double original[] = {1.0, 2.0, 3.0, 4.0, 5.0};
    FILE* binary_data = fopen("numbers.bin", "wb");
    fwrite(original, sizeof(double), 5, binary_data);
    fclose(binary_data);
    
    double retrieved[5];
    binary_data = fopen("numbers.bin", "rb");
    size_t elements_read = fread(retrieved, sizeof(double), 5, binary_data);
    
    if (elements_read == 5) {
        for (int i = 0; i < 5; i++) {
            printf("%.1f ", retrieved[i]);
        }
    } else {
        if (feof(binary_data)) {
            printf("Unexpected end of file\n");
        } else if (ferror(binary_data)) {
            perror("Read error");
        }
    }
    
    fclose(binary_data);
    binary_data = NULL;
    return 0;
}

Buffer Management

The standard library uses memory buffers to optimize file I/O operations. Data moves between:

  1. Application memory
  2. System buffer
  3. Storage device
#include <windows.h>

int main() {
    FILE* buffered_file = fopen("delayed.txt", "w");
    fputs("buffer test", buffered_file);
    
    printf("Data written to buffer - file empty\n");
    Sleep(5000);
    
    printf("Flushing buffer\n");
    fflush(buffered_file);
    
    printf("Data now visible in file\n");
    Sleep(5000);
    
    fclose(buffered_file);
    buffered_file = NULL;
    return 0;
}

Tags: c programming file operations data persistence File I/O buffer management

Posted on Fri, 08 May 2026 23:47:26 +0000 by rsassine