Write and read a binary file (System Calls: ''open'', ''write'', ''read'' and ''close'')

Concepts:

Use the system calls open, write, read and close for writing and reading a binary file.

Text:
After the writing of a vector of structures (the elements of the structure are a vector of characters containing the name of a student, a variable of type unsigned int containing the student identifier and a variable of type float containing the average value of the scores of the exams attended by the student), the program must:

Video solution:
Video with the explanation of the solution:

Solution:

binary_file_write_read.c
/* Write and read a binary file using system calls
   (open, write, read e close) */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> /* For system calls write, read e close */
 
#include <sys/types.h> /* For system call open */
#include <sys/stat.h>  /* For system call open */
#include <fcntl.h>     /* For system call open */
 
 
#define LEN 50
#define N_STUD 2
 
typedef struct stud{
  char name[LEN+1];
  unsigned int id;
  float average;
}stud_t;
 
 
int main() {
  int fd; /* NOTE: fd is an integer, not a FILE* */
  stud_t student[N_STUD];
  int i;
  unsigned int n_stud;
 
  strcpy(student[0].name, "Steven");
  student[0].id = 120000;
  student[0].average = 25.5;
 
  strcpy(student[1].name, "Julia");
  student[1].id = 120001;
  student[1].average = 28.5;
 
  /* When in the function open the option O_CREAT is specified
  as a second argument (i.e., create the file if it does not exist),
  a third argument which specifies the permission used for the 
  creation of the new file is needed. The third argument is not 
  needed if the option O_CREAT has not been specified.
 
  Examples of the third argument:
  S_IRUSR 400 Read permission for the owner
  S_IWUSR 200 Write permission for the owner
  S_IRGRP 040 Read permission for the group
  S_IROTH 004 Read permission for other users
 
  Using the previous options, the file will be created with the 
  permissions 644, i.e., -rw-r--r--
 */
 
 
  fd = open("out.bin", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); /* Open the file for writing */
  if (fd == -1) { /* In the case of error, open returns -1 ! */
    printf("Errore: impossibile aprire il file out.bin\n");
    exit(1);
  }
 
 
  /* Write the file */
  /* NOTE 2: a binary file sometimes cannot be readable 
     correctly in a PC that it is not the one which generates it, 
     because, for instance, integer numbers can be coded with a
     different number of bytes.
  */
 
  /* Write in binary all the data contained in the structure */
  write(fd, student, N_STUD*sizeof(stud_t)); 
 
  /* DIMENSION OF THE GENERATED FILE
     The dimension of the generated file will be:
     n_stud*sizeof(stud_t)
     in the case of the computer used to test the program:
     2*60 = 120 byte
  */
 
  close(fd); /* Close the file */
 
 
 
  fd = open("out.bin", O_RDONLY); /* Open the file for reading */
  if (fd == -1){
    printf("Error: file out.bin cannot be opened\n");
    exit(1);
  }
 
  /* Read the file */
  n_stud = 0;
  while( read(fd, &student[n_stud], sizeof(stud_t)) == sizeof(stud_t) ) {
    n_stud++;
  }
 
  close(fd); /* Close the file */
 
 
  /* Print the read records */
  for (i=0; i<n_stud; i++) {
    printf("%s %d %f\n", student[i].name, student[i].id, student[i].average);
  }
 
 
  return 0;
}