The C standard library I/O functions allow you to read and write data to both files and devices. There are no predefined file structures in C, all data being treated as a sequence of bytes. These I/O functions may be broken into two different categories : stream I/O and low-level I/O.
The stream I/O functions treat a data file as a stream of individual characters. The appropriate stream function can provide buffered, formatted or unformatted input and output of data, ranging from single characters to complicated structures. Buffering streamlines the I/O process by providing temporary storage for data which takes away the burden from the system of writing each item of data directly and instead allows the buffer to fill before causing the data to be written.
The low-level I/O system on the other hand does not perform any buffering or formatting of data --instead it makes direct use of the system's I/O capabilities to transfer usually large blocks of information.
The C I/O system provides a consistent interface to the programmer independent of the actual device being accessed. This interface is termed a stream in C and the actual device is termed a file. A device may be a disk or tape drive, the screen, printer port, etc. but this does not bother the programmer because the stream interface is designed to be largely device independent. All I/O through the keyboard and screen that we have seen so far is in fact done through special standard streams called stdin and stdout for input and output respectively. So in essence the console functions that we have used so far such as printf(), etc. are special case versions of the file functions we will now discuss.
There are two types of streams : text and binary. These streams are basically the same in that all types of data can be transferred through them however there is one important difference between them as we will see.
A text stream is simply a sequence of characters. However the characters in the stream are open to translation or interpretation by the host environment. For example the newline character, ' ', will normally be converted into a carriage return/linefeed pair and ^Z will be interpreted as EOF. Thus the number of characters sent may not equal the number of characters received.
A binary stream is a sequence of data comprised of bytes that will not be interfered with so that a one-to-one relationship is maintained between data sent and data received.
fopen() | open a stream |
fclose() | close a stream |
putc()& fputc() | write a character to a stream |
getc()& fgetc() | read a character from a stream |
fprintf()& fscan | formatted I/O |
fgets() & fputs() | string handling |
fseek() | position the file pointer at a particular byte |
feof() | tests if EOF |
A stream is associated with a specific file by performing an open operation. Once a file is opened information may be exchanged between it and your program. Each file that is opened has a unique file control structure of type FILE ( which is defined in
FILE *fptr ;
The fopen() function opens a stream for use and links a file with that stream returning a valid file pointer which is positioned correctly within the file if all is correct. fopen() has the following prototype
FILE *fopen( const char *filename, const char *mode );
where filename is a pointer to a string of characters which make up the name and path of the required file, and mode is a pointer to a string which specifies how the file is to be opened. The following table lists some values for mode.
r | opens a text file for reading (must exist) |
w | opens a text file for writing (overwritten or created) |
a | append to a text file |
rb | opens a binary file for reading |
wb | opens a binary file for writing |
ab | appends to a binary file |
r+ | opens a text file for read/write (must exist) |
w+ | opens a text file for read/write |
a+ | append a text file for read/write |
rb+ | opens a binary file for read/write |
wb+ | opens a binary file for read/write |
ab+ | append a binary file for read/write |
If fopen( ) cannot open "test.dat " it will a return a NULL pointer which should always be tested for as follows.
FILE *fp ; if ( ( fp = fopen( "test.dat", "r" ) ) == NULL ) { puts( "Cannot open file") ; exit( 1) ; }
This will cause the program to be exited immediately if the file cannot be opened. The fclose() function is used to disassociate a file from a stream and free the stream for use again.
fclose( fp ) ;
fclose() will automatically flush any data remaining in the data buffers to the file.
Once a file pointer has been linked to a file we can write characters to it using the fputc() function.
fputc( ch, fp ) ;
If successful the function returns the character written otherwise EOF. Characters may be read from a file using the fgetc() standard library function.
ch = fgetc( fp ) ;
When EOF is reached in the file fgetc( ) returns the EOF character which informs us to stop reading as there is nothing more left in the file.
For Example :- Program to copy a file byte by byte
#include <stdio.h> void main() { FILE *fin, *fout ; char dest[30], source[30], ch ; puts( "Enter source file name" ); gets( source ); puts( "Enter destination file name" ); gets( dest ) ; if ( ( fin = fopen( source, "rb" ) ) == NULL ) // open as binary as we don’t {// know what is in file puts( "Cannot open input file ") ; puts( source ) ; exit( 1 ) ; } if ( ( fout = fopen( dest, "wb" ) ) == NULL ) { puts( "Cannot open output file ") ; puts( dest ) ; exit( 1 ) ; } while ( ( ch = fgetc( fin ) ) != EOF ) fputc( ch , fout ) ; fclose( fin ) ; fclose( fout ) ; }
NOTE : When any stream I/O function such as fgetc() is called the current position of the file pointer is automatically moved on by the appropriate amount, 1 character/ byte in the case of fgetc() ;
This is quite similar to working with characters except that we use the functions fgets() and fputs() whose prototypes are as follows :-
int fputs( const char *str, FILE *fp ) ; char *fgets( char *str, int maxlen, FILE *fp ) ;
For Example : Program to read lines of text from the keyboard, write them to a file and then read them back again.
#include <stdio.h> void main() { char file[80], string[80] ; FILE *fp ; printf( "Enter file Name : " ); gets( file ); if (( fp = fopen( file, "w" )) == NULL )//open for writing { printf( "Cannot open file %s", file ) ; exit( 1 ) ; } while ( strlen ( gets( str ) ) > 0 ) { fputs( str, fp ) ; fputc( "\n", fp ) ; /* must append \n for readability -- not stored by gets() */ } fclose( fp ) ; if (( fp = fopen( file, "r" )) == NULL )//open for reading { printf( "Cannot open file %s", file ) ; exit( 1 ) ; } while (fgets( str, 79, fptr ) != EOF )// read at most 79 characters puts( str ) ; fclose( fp ) ; }
All Rights Reserved. © 2024 BookOfNetwork