The C programming language provides many standard library functions for file input and output. These functions make up the bulk of the C standard library header<stdio.h>.
The I/O functionality of C is fairly low-level by modern standards; C abstracts all file operations into operations on streams of bytes, which may be "input streams" or "output streams". Unlike some earlier programming languages, C has no direct support for random-access data files; to read from a record in the middle of a file, the programmer must create a stream, seek to the middle of the file, and then read bytes in sequence from the stream.
The stream model of file I/O was popularized by the Unix operating system, which was developed concurrently with the C programming language itself. The vast majority of modern operating systems have inherited streams from Unix, and many languages in the C programming language family have inherited C's file I/O interface with few if any changes (for example, PHP). The C++ standard library reflects the "stream" concept in its syntax; see iostream.
Most of the C file input/output functions are defined in/stdio.h (/cstdio header in C++).
Thefgetc function is used to read a character from a stream.
intfgetc(FILE*fp);
If successful,fgetc returns the next byte or character from the stream (depending on whether the file is "binary" or "text", as discussed underfopen above). If unsuccessful, fgetc returnsEOF. (The specific type of error can be determined by callingferror orfeof with the file pointer.)
The standard macrogetc, also defined in<stdio.h>, behaves in almost the same way asfgetc, except that—being a macro—it may evaluate its arguments more than once.
The standard functiongetchar, also defined in<stdio.h>, takes no arguments, and is equivalent togetc(stdin).
A mistake when usingfgetc,getc, orgetchar is to assign the result to a variable of typecharbefore comparing it toEOF. The following code fragments exhibit this mistake, and then show the correct approach (using type int):
| Mistake | Correction |
|---|---|
charc;while((c=getchar())!=EOF)putchar(c); | intc;/* This will hold the EOF value */while((c=getchar())!=EOF)putchar(c); |
Consider a system in which the typechar is 8 bits wide, representing 256 different values.getchar may return any of the 256 possible characters, and it also may returnEOF to indicate end-of-file, for a total of 257 different possible return values.
Whengetchar's result is assigned to achar, which can represent only 256 different values, there is necessarily some loss of information—when packing 257 items into 256 slots, there must be a collision. TheEOF value, when converted tochar, becomes indistinguishable from whichever one of the 256 characters shares its numerical value. If that character is found in the file, the above example may mistake it for an end-of-file indicator; or, just as bad, if typechar is unsigned, then becauseEOF is negative, it can never be equal to any unsignedchar, so the above example will not terminate at end-of-file. It will loop forever, repeatedly printing the character which results from convertingEOF tochar.
However, this looping failure mode does not occur if the char definition is signed (C makes the signedness of the default char type implementation-dependent),[1] assuming the commonly usedEOF value of -1. However, the fundamental issue remains that if theEOF value is defined outside of the range of thechar type, when assigned to achar that value is sliced and will no longer match the fullEOF value necessary to exit the loop. On the other hand, ifEOF is within range ofchar, this guarantees a collision betweenEOF and a char value. Thus, regardless of how system types are defined, never usechar types when testing againstEOF.
On systems whereint andchar are the same size (i.e., systems incompatible with minimally the POSIX and C99 standards), even the "good" example will suffer from the indistinguishability ofEOF and some character's value. The proper way to handle this situation is to checkfeof andferror aftergetchar returnsEOF. Iffeof indicates that end-of-file has not been reached, andferror indicates that no errors have occurred, then theEOF returned bygetchar can be assumed to represent an actual character. These extra checks are rarely done, because most programmers assume that their code will never need to run on one of these "bigchar" systems. Another way is to use a compile-time assertion to make sure thatUINT_MAX > UCHAR_MAX, which at least prevents a program with such an assumption from compiling in such a system.
In the C programming language, thefread andfwrite functions respectively provide the file operations of input and output.fread andfwrite are declared in<stdio.h>.
fwrite is defined as
size_tfwrite(constvoid*array,size_tsize,size_tcount,FILE*stream);
fwrite function writes a block of data to the stream. It will write an array ofcount elements to the current position in the stream. For each element, it will writesize bytes. The position indicator of the stream will be advanced by the number of bytes written successfully.
The function will return the number of elements written successfully. The return value will be equal tocount if the write completes successfully. In case of a write error, the return value will be less thancount.
The following program opens a file namedsample.txt, writes a string of characters to the file, then closes it.
#include<stdio.h>#include<string.h>#include<stdlib.h>intmain(void){FILE*fp;size_tcount;constchar*str="hello\n";fp=fopen("sample.txt","w");if(fp==NULL){perror("failed to open sample.txt");returnEXIT_FAILURE;}count=fwrite(str,1,strlen(str),fp);printf("Wrote %zu bytes. fclose(fp) %s.\n",count,fclose(fp)==0?"succeeded":"failed");returnEXIT_SUCCESS;}
Thefputc function is used to write a character to a stream.
intfputc(intc,FILE*fp);
The parameterc is silently converted to anunsigned char before being output. If successful,fputc returns the character written. If unsuccessful, fputc returnsEOF.
The standard macroputc, also defined in<stdio.h>, behaves in almost the same way asfputc, except that—being a macro—it may evaluate its arguments more than once.
The standard functionputchar, also defined in<stdio.h>, takes only the first argument, and is equivalent toputc(c, stdout) wherec is that argument.
The following C program opens a binary file calledmyfile, reads five bytes from it, and then closes the file.
#include<stdio.h>#include<stdlib.h>intmain(void){constintcount=5;/* count of bytes to read from file */charbuffer[count]={0};/* initialized to zeroes */inti,rc;FILE*fp=fopen("myfile","rb");if(fp==NULL){perror("Failed to open file\"myfile\"");returnEXIT_FAILURE;}for(i=0;(rc=getc(fp))!=EOF&&i<count;buffer[i++]=rc);fclose(fp);if(i==count){puts("The bytes read were...");for(i=0;i<count;i++)printf("%x ",buffer[i]);puts("");}elsefputs("There was an error reading the file.\n",stderr);returnEXIT_SUCCESS;}