Skip to content

Instantly share code, notes, and snippets.

@cbourke
Created October 23, 2018 01:30
Show Gist options
  • Select an option

  • Save cbourke/6e2a16e2398a29e967df35366e8436eb to your computer and use it in GitHub Desktop.

Select an option

Save cbourke/6e2a16e2398a29e967df35366e8436eb to your computer and use it in GitHub Desktop.
auto-posted gist

File I/O

  • A file is a unit of stored memory, usually on disk
  • A file can also be: directories, buffers (standard input/output are files), a socket could be a file, a program is a file
  • You can write to and read from a file
  • Files may be plaintext or binary (or plaintext but not intended for human consumption: EDI, XML, JSON, base-64 encoding)
  • The basic steps to follow are:
    1. Open the file
    2. Process the file
    3. Close the file

File I/O in C

Opening a File

  • There is a special FILE * pointer type built into the standard library
  • To open a file you use fopen()
  • It takes two arguments: the path/name of the file you want to open (string) and a "mode": "r" (input) or "w" (output)
//open a file called data.txt in the current directory for reading:
FILE *f = fopen("data.txt", "r");

//open a file for writing in the current working directory:
FILE *g = fopen("output.dat", "w");

//use relative paths:
FILE *f = fopen("../../data.txt", "r");

//absolute paths:
FILE *f = fopen("/etc/passwd", "r");

//absolute paths are also allowed:
FILE *f = fopen("/etc/shadow", "r");
  • If fopen fails it returns NULL
  • If you don't have read/write permissions for example
  • If you open a file for writing that already exists, it will be overwritten!
  • If you open a file for writing that does not already exist, it will generally be created for you
  • Once you are done with the file, you should close the file: fclose()
FILE *f = fopen("data.txt", "r");
//... process the file
fclose(f);
  • Failure to properly close a file may corrupt the file contents

File Output (Plaintext)

  • There are many ways to do file output (writing) to a file
  • We're going to focus on one: fprintf
  • The only difference: fprintf accepts an additional first argument: the file pointer ("handle") to print to

File Input

  • There are many (dangerous) ways to do file input

  • I'm going to limit it to two SAFE ways

  • fgetc reads a single character from the file and returns its value, it also advances the file pointer to the next character

  • At the end of a file, fgetc returns a special EOF (end of file) "character"

  • Instead, you can read an entire line from a file using fgets

  • fgets gets up to a single line, but limited to the number of bytes you specify

  • fgets reads an entire string from a file, *fgets(char *s, int size, FILE *stream);

    • s is the string that the contents are loaded into (it needs to be big enough to hold how ever much you are reading)
    • size is the limit: fgets reads at most size - 1 bytes from the file (minus to accommodate the null terminating character, which it automatically inserts for you), BUT it stops when it sees the first endline character
    • NOTE: fgets retains the endline character in the resulting string!
    • stream is the file you are reading from
     //read the first 50 characters from the file:
       int i;
       char c;
       for(i=0; i<50; i++) {
         //read a character
         c = fgetc(f);
         //print it out
         printf("character is %c\n", c);
       }
	//read all the lines from the file:
	  int numLines = 0;
	  char buffer[200];
	  char *s = fgets(buffer, 200, f);
	  while(s != NULL) {
	    numLines++;
	    //read a line
	    //note: fgets preserves the endline character if it is read
	    //note: fgets returns a string pointer (char *) which is equal to
	    //      the buffer it reads into upon success, otherwise, upon failure
	    //      or the end of a file, it returns... NULL

	    //it is common to "chomp" or "trim" any trailing or leading whitespace
	    buffer[strlen(buffer)-1] = '\0';
	    //print it out
	    printf("line is %s\n", buffer);
	    s = fgets(buffer, 200, f);

	  }
  • fgets retains endline characters
  • You can always "chomp" them out if needed
  • You can tell you are done reading from a file because fgets returns a char * pointer, which will be NULL at the end of the file
  • IN contrast, fgetc returns a special EOF flag value

Binary Data in C

  • C provides two functions, fread for reading binary data and fwrite for writing binary data
  • size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);














Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment