File Handling

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


File Positioning in C: fseek, ftell, and rewind

In C programming, file positioning functions allow you to move the file pointer to different locations within a file. This is essential for reading or writing data at specific points and enables more flexible file access than sequential reading or writing alone. The primary functions for file positioning are fseek, ftell, and rewind.

fseek: Moving the File Pointer

The fseek function is used to move the file pointer to a specified location within a file. Its syntax is:

int fseek(FILE *stream, long int offset, int whence);
  • stream: A pointer to the FILE object associated with the open file.
  • offset: The number of bytes to move the file pointer. This can be positive (forward), negative (backward), or zero.
  • whence: Specifies the reference point from which the offset is applied. It can be one of the following macros:
    • SEEK_SET: Beginning of the file. The offset is relative to the start of the file.
    • SEEK_CUR: Current position of the file pointer. The offset is relative to the current position.
    • SEEK_END: End of the file. The offset is relative to the end of the file. Note that using a positive offset with SEEK_END is undefined behavior.

fseek returns 0 on success and a non-zero value on failure (e.g., attempting to seek beyond the file boundaries). It's crucial to check the return value of fseek to ensure the operation was successful.

Example: Moving to the beginning of the 10th record (assuming each record is 50 bytes):

#include <stdio.h>

int main() {
    FILE *fp;
    long int offset;
    int record_size = 50; // Size of each record in bytes
    int record_number = 10; // Accessing the 10th record

    fp = fopen("data.txt", "r"); // Open the file in read mode

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

    offset = (record_number - 1) * record_size; // Calculate the offset

    if (fseek(fp, offset, SEEK_SET) == 0) {
        printf("Successfully moved to the beginning of the %dth record.\n", record_number);
        // Now you can read the data from the 10th record
        char buffer[record_size + 1]; // +1 for null terminator if you're reading strings
        if (fread(buffer, 1, record_size, fp) == record_size) {
            buffer[record_size] = '\\0'; // Null-terminate the string if you expect a string
            printf("Data read: %s\n", buffer);
        } else {
            perror("Error reading record");
        }
    } else {
        perror("Error seeking in file");
    }

    fclose(fp);
    return 0;
} 

ftell: Determining the File Pointer Position

The ftell function returns the current position of the file pointer in bytes, relative to the beginning of the file. Its syntax is:

long int ftell(FILE *stream);

ftell returns the current file pointer position as a long int or -1L on error. This is useful for saving the current position and returning to it later.

Example: Getting the current file pointer position after reading some data:

#include <stdio.h>

int main() {
    FILE *fp;
    long int position;
    char buffer[20];

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

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

    // Read some data
    fread(buffer, 1, 10, fp);
    buffer[10] = '\\0';
    printf("Read data: %s\n", buffer);

    // Get the current file pointer position
    position = ftell(fp);

    if (position != -1L) {
        printf("Current file pointer position: %ld bytes\n", position);
    } else {
        perror("Error getting file position");
    }

    fclose(fp);
    return 0;
} 

rewind: Resetting the File Pointer

The rewind function sets the file pointer to the beginning of the file. Its syntax is:

void rewind(FILE *stream);

rewind does not return a value. It is equivalent to calling fseek(stream, 0, SEEK_SET), except that it also clears the error and end-of-file indicators for the stream.

Example: Rewinding the file pointer after reading some data:

#include <stdio.h>

int main() {
    FILE *fp;
    char buffer1[20], buffer2[20];

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

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

    // Read some data
    fread(buffer1, 1, 10, fp);
    buffer1[10] = '\\0';
    printf("First read: %s\n", buffer1);

    // Rewind the file pointer
    rewind(fp);

    // Read the same data again (from the beginning)
    fread(buffer2, 1, 10, fp);
    buffer2[10] = '\\0';
    printf("Second read (after rewind): %s\n", buffer2);

    fclose(fp);
    return 0;
} 

Accessing Specific Records or Sections

The power of fseek, ftell, and rewind lies in their ability to access specific parts of a file. Combining these allows for features like random access to records in a database file or parsing specific sections of a configuration file. Remember to handle error conditions and carefully calculate offsets based on your data structure and file format.