Programming in C

File I/O

Gerald Senarclens de Grancy

Purpose of File I/O

  • Store persistent data
    • Write the results of your computations to files
    • Keep a log of errors
    • Store intermediate results
  • Load previously stored files

File Types

Text

+
Human readable
Multiple powerful standards like CSV, XML, JSON and YAML
Can usually be compressed
-
Hard to parse manually
Require more memory

Binary

+
Require less memory
Are easy to write and load if the exact format is known
-
Not human readable
Editing with a hex editor is tedious
Cannot be read when the format is not known

C API

All required functions are provided by <stdio.h>

fopen(.) opens files; if opening fails, NULL is returned

FILE *fopen(const char *pathname, const char *mode);

fprintf(.) and fwrite(.) write text and binary data to open files

int fprintf(FILE *stream, const char *format, ...);
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

fclose(.) writes buffered output and frees the file pointer's resources

int fclose(FILE *stream);  // on successful completion, 0 is returned

Text Files

Example: Writing Text

#include <stdio.h>  // provides fopen, fprintf and fclose

int main() {
  int num = 15;
  FILE* f = fopen("data.txt", "w");  // open for writing

  if(f == NULL) {  // we have to check if opening was successful
    fprintf(stderr, "Error!");
    return 1;
  }

  fprintf(f, "%d\n", num);
  fprintf(f, "This is a text\n");
  fclose(f);

  return 0;
}
Download write_text.c

Example: Appending Text

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

int main() {
  FILE* f = fopen("data.txt", "a");  // open for appending

  if(f == NULL) {  // we have to check if opening was successful
    fprintf(stderr, "Error!");
    return EXIT_FAILURE;
  }

  fprintf(f, "%.2lf\n", 36.8);
  fprintf(f, "Additional text\n");
  fclose(f);

  return 0;
}
Download append_text.c

Reading Text

#include <stdio.h>
int main() {
  int num;
  FILE* f = fopen("data.txt","r");
  if(f == NULL) {
    fprintf(stderr, "Error!");
    return 1;
  }
  char line[100];  // a fixed size buffer for reading
  fgets(line, sizeof(line), f);
  sscanf(line, "%d\n", &num);
  printf("Value in the file times two: %d\n", num * 2);
  fgets(line, sizeof(line), f);
  puts(line);
  fclose(f);
  return 0;
}
Download read_text.c

Binary Files

Example: Writing Data

#include <stdio.h>
typedef struct data {
  int first;
  int second;
} Data;
int main() {
  Data d = {.first=1724, .second=255};
  FILE* f = fopen("data.bin","wb");
  if (f == NULL) { fputs("Error!", stderr); return 1; }
  fwrite(&d, sizeof(Data), 1, f);
  fclose(f);
  return 0;
}
Download write_binary.c

Example: Reading Data

#include <stdio.h>

typedef struct data {
  int first;
  int second;
} Data;
int main() {
  Data d;
  FILE* f = fopen("data.bin","rb");
  if (f == NULL) { fputs("Error!", stderr); return 1; }
  fread(&d, sizeof(d), 1, f);
  fclose(f);
  printf("first: %d, second: %d\n", d.first, d.second);
  return 0;
}
Download read_binary.c

Example: Write Array

#include <stdio.h>
#include <limits.h>


int main() {
  unsigned int arr[] = { 0, UINT_MAX, 255, 0xff000000, 1724 };
  FILE* f = fopen("array.bin","wb");
  if (f == NULL) { fputs("Error!", stderr); return 1; }
  fwrite(arr, sizeof(unsigned int), sizeof(arr) / sizeof(unsigned int), f);
  fclose(f);
  return 0;
}
Download write_array.c

Start by investigating the file size (eg. ls -l)

Decode the values of the array: xxd [-b] file.bin (hint: endianness)

Dec Hex  Bin      Dec Hex  Bin
  0   0 0000        8   8 1000
  1   1 0001        9   9 1001
  2   2 0010       10   A 1010
  3   3 0011       11   B 1011
  4   4 0100       12   C 1100
  5   5 0101       13   D 1101
  6   6 0110       14   E 1110
  7   7 0111       15   F 1111
      

Investigate with a proper hex editor (eg. Okteta w/ Tools->Decoding Table)

Exercise

  1. Write your name in a text file. Then write a C program to read that file and print its content to stdout.
  2. Write a C program that loads the array written by write_array.c. The program must print all numbers in the array to stdout, separated by commas.

Questions
and feedback...