- 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:
- Open the file
- Process the file
- Close the 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
fopenfails it returnsNULL - 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
- There are many ways to do file output (writing) to a file
- We're going to focus on one:
fprintf - The only difference:
fprintfaccepts an additional first argument: the file pointer ("handle") to print to
-
There are many (dangerous) ways to do file input
-
I'm going to limit it to two SAFE ways
-
fgetcreads 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,
fgetcreturns a specialEOF(end of file) "character" -
Instead, you can read an entire line from a file using
fgets -
fgetsgets up to a single line, but limited to the number of bytes you specify -
fgetsreads an entire string from a file,*fgets(char *s, int size, FILE *stream);sis the string that the contents are loaded into (it needs to be big enough to hold how ever much you are reading)sizeis the limit:fgetsreads 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:
fgetsretains the endline character in the resulting string! streamis 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);
}fgetsretains endline characters- You can always "chomp" them out if needed
- You can tell you are done reading from a file because
fgetsreturns achar *pointer, which will beNULLat the end of the file - IN contrast,
fgetcreturns a specialEOFflag value
- C provides two functions,
freadfor reading binary data andfwritefor writing binary data size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream);