NANDHOO.

File System and I/O Operations

Chapter 17: File System and I/O Operations


In Unix-like systems (and by extension C), "everything is a file." Whether you are writing to a hard drive, a keyboard, or a network socket, the C standard library provides a unified interface for Input/Output (I/O).


I. Streams and the FILE Pointer


C uses Streams to handle I/O. A stream is an abstraction that represents a flow of data. The standard library uses the FILE * type to manage these streams.


Standard Streams

  • stdin: Standard Input (Keyboard)
  • stdout: Standard Output (Console)
  • stderr: Standard Error (Console, for error messages)

II. Working with Files


The basic lifecycle of file I/O involves: Open -> Process -> Close.


#include <stdio.h>

int main() { FILE *fptr; fptr = fopen("data.txt", "w"); // Open for writing


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

fprintf(fptr, "Hello File System!\n");
fclose(fptr); // Crucial to flush buffers and release handles
return 0;

}


Common Modes for fopen

  • "r": Read (fails if file doesn't exist).
  • "w": Write (creates file or overwrites).
  • "a": Append (adds to end of file).
  • "r+": Read and Write.

III. Formatted vs. Character I/O


  1. Formatted: fprintf and fscanf. Use these for text data where you want to read/write numbers and strings.
  2. Character: fgetc and fputc. Process one character at a time.
  3. Line: fgets and fputs. Read/write an entire line. Avoid gets() as it is highly insecure.

IV. Binary I/O: fread and fwrite


When working with images, audio, or database records, you don't want to translate data to text. You want to write raw bytes.


struct Record { int id; float value; };
struct Record r = {1, 99.5f};

// Write a whole struct directly to disk fwrite(&r, sizeof(struct Record), 1, fptr);


ProgramBuffer PoolOS KernelPage CacheDisk


V. Random Access: fseek and ftell


You can move the "file pointer" to any byte position in the file.

  • fseek(fp, offset, origin): Move to a position. SEEK_SET (start), SEEK_CUR (current), SEEK_END (end).
  • ftell(fp): Get the current byte position.

VI. Error Handling: feof and ferror


Always check for the end-of-file (feof) and potential disk errors (ferror). Using perror prints a human-readable error message based on the global errno variable.