Creating and linking a stream to a disk file is called opening a file. When a file is opened, it is available to the OS for reading, writing or both.
Opening a file with fopen()
The fopen() library function is used to open a file:
FILE *fopen(const char *filename, const char *mode);
The fopen call will initialise a structure of type FILE, which contains all the information necessary to control the stream. If fopen() fails, it returns NULL.
The parameter filename contains the name and address of the file to be opened. The filename argument can be a literal string enclosed in double quotation marks or a pointer to a string variable. The parameter mode specifies the mode in which to open the file. The file may be binary or text and may be opened for reading, writing, or both. Values of mode for the fopen() function are listed below.
Sr.No. | Mode & Description |
---|---|
r | Opens an existing text file for reading. |
w | Opens a text file for writing. If it does not exist, then a new file is created. Here your program will start writing content from the beginning of the file. |
a | Opens a text file for writing in appending mode. If it does not exist, then a new file is created. Here your program will start appending content in the existing file content. |
r+ | Opens a text file for both reading and writing. |
w+ | Opens a text file for both reading and writing. It first truncates the file to zero length if it exists, otherwise creates a file if it does not exist. |
a+ | Opens a text file for both reading and writing. It creates the file if it does not exist. The reading will start from the beginning but writing can only be appended. |
Closing a File
To close a file, use the fclose( ) function. The prototype of this function is −
int fclose( FILE *fp );
The fclose() function returns zero on success, or EOF if there is an error in closing the file. When a file is closed, the file’s buffer is flushed (written to the disk) and the memory is released.
Formatted V Unformatted Input/Output
Formatted input/output functions are for reading and writing data in a certain format. Format strings specify the type and format of this data. The format string contains placeholders or format specifiers, which start with the % character and are followed by a format specifier character representing the type of data being read or written. Unformatted input/output functions are for reading/writing character data without regard to its format.
Writing to a File.
Unformatted output with fputc
Writes the character value c to the output stream referenced by fp. The prototype is −
int fputc( int c, FILE *fp );
If successful it returns the written character written or EOF if there is an error.
Unformatted output with fputs
Writes a line of characters s to the output stream referenced by fp
int fputs( const char *s, FILE *fp );
It successful it returns a non-negative value otherwise EOF.
Unformatted output with putw
The putw() function writes an integer i to the output stream fp.
int putw( int i, FILE *fp );
If successful it returns a non-negative value otherwise EOF.
Formatted output using fprintf
Writes a formatted string to a specified output stream. The first parameter is a pointer to the output stream. The second argument is a pointer to a char that contains the text to be written and may include format characters. Ellipses represent a variable number of additional arguments.
int fprintf ( FILE * stream, const char * format, ... );
If successful, the total number of characters written is returned. If a writing error occurs a negative number is returned.
When the code below is compiled and executed, it creates a new file test.txt and writes two lines of text using the fprintf() and fputs() function.
#include <stdio.h> main() { FILE *fp; fp = fopen("test.txt", "w+"); fprintf(fp, "create output file...\n"); fputs("Use fputs file...\n", fp); fclose(fp); }
Direct output with fwrite
The fwrite() function is used to write records (a sequence of bytes) to the output stream. The fwrite() function accepts four arguments.
ptr points to the block of memory which contains the data items to be written.
size specifies the number of bytes of each item to be written.
n is the number of items to be written.
FILE* is a pointer to the file where data items will be written in binary mode.
fwrite( ptr, int size, int n, FILE *fp );
If successful fwrite returns the number of items successfully written. If an error occurs, the return value may be less than total number of items written
When the code below is compiled and executed, it creates a new file file.txt and writes the contents of the char array to the output stream using the fwrite() function.
#include<stdio.h> int main () { FILE *fp; char str[] = "programming windows"; fp = fopen( "file.txt" , "w" ); fwrite(str , 1 , sizeof(str) , fp ); fclose(fp); return(0); }
Reading from a file
Unformatted input with fgetc
The fgetc() function reads a character from the input file referenced by fp. The prototype of fgetc() is-
int fgetc( FILE * fp );
Returns the character read or EOF is there is an error.
Unformatted Input with fgets
The function fgets() reads up to n-1 characters from the input stream referenced by fp and stores it into the string pointed to by str.
char *fgets( char *str, int n, FILE *fp );
If successful the fgets() function returns a pointer to the string buffer. A NULL return value indicates an error or an end-of-file condition
Unformatted Input with getw
Reads binary data from a file. A pointer to the file stream is the only argument.
int getw(FILE *stream);
If successful it returns a non-negative value otherwise EOF.
Formatted fscanf file input
The fscanf() function reads formatted input from a file. The parameter fp is a pointer to type FILE returned by fopen(). The parameter fmt is a pointer to the format string that specifies how fscanf() is to read the input. The ellipses ( … ) indicate one or more additional arguments.
int fscanf(FILE *fp, const char *fmt, ...);
On success, the function returns the number of items of the argument list successfully filled. It returns zero or EOF, if unsuccessful.
When the code below is compiled and executed, it opens the file file.txt and reads the file contents into the char array str.
#include <stdio.h> int main () { char str[20]; FILE * fp; fp = fopen ("file.txt", "r"); fscanf(fp, "%s", str); printf("%s\n", str ); fclose(fp); return(0); }
Direct input with the fread()
The fread() function is used to read binary data and is complementary to fwrite(). The fread() function accepts four arguments.
ptr is the address of the memory block where data is stored after reading.
size specifies the number of bytes of each item to be read.
n is the number of items read from the file where each item occupies the number of bytes specified in the second argument.
FILE* is the file from where the data is read in binary mode.
fread( ptr, int size, int n, FILE *fp );
On success, it reads n items from the file and returns n. On error or end of the file, it returns a number less than n.
When the code below is compiled and executed, it opens the file file.txt and reads the contents into char array buffer.
#include<stdio.h> int main () { FILE *fp; char buffer[100]; fp = fopen("file.txt", "r"); fread(buffer, 20, 1, fp); printf("%s\n", buffer); fclose(fp); return(0); }
Sequential Versus Random File Access
Every file IO operation has a position indicator indicating where data is read from and written to. The position is always given in terms of bytes from the beginning of the file. When the data in a file is read or written sequentially the file indicator position is taken care of automatically.
Manual control over the file position indicator is known as random file access. This means that the programmer can read data from or write data to any position in a file without reading or writing all the preceding data.
ftell() and rewind()
To move the position indicator to the beginning of a file, use the function rewind(). The prototype is
void rewind(FILE *fp);
The parameter fp is the FILE pointer associated with the stream. After calling rewind() the file’s position indicator is set to the beginning of the file (byte 0).
To determine the value of a file’s position indicator, use function ftell(). The prototype is
long ftell(FILE *fp);
The argument fp is the FILE pointer returned by fopen(). ftell() returns a type long that gives the current file position in bytes from the start of the file (the first byte is at position 0). If an error occurs, ftell() returns -1L
fseek()
fseek() sets the position of file indicator to anywhere in the file. The function prototype is
int fseek(FILE *fp, long offset, int origin);
The argument fp is the FILE pointer associated with the file. The distance to move the position indicator is given by offset in bytes, the argument origin specifies the move’s relative starting point.
There can be three values for origin. The symbolic constants are defined in io.h
SEEK_SET 0 – Moves the indicator offset bytes from the beginning of the file.
SEEK_CUR 1 – Moves the indicator offset bytes from its current position.
SEEK_END 2 – Moves the indicator offset bytes from the end of the file.
#include <stdlib.h> #include <stdio.h> #define BUFLEN 6 char readdate[] = "abcdefghijklmnopqrstuvwxyz"; int main( void ) { FILE *fp; char buf[2]; if ( (fp = fopen("random.TXT", "w")) == NULL) { fprintf(stderr, "Error opening file."); exit(1); } if (fputs(readdate, fp) == EOF) { fprintf(stderr, "Error writing to file."); exit(1); } fclose(fp); if ( (fp = fopen("random.TXT", "r")) == NULL) { fprintf(stderr, "Error opening file."); exit(1); } printf("\nAfter opening the file the file pointer is at position = %ld", ftell(fp)); fgets(buf,2, fp);//read first character printf("\nThe character at position zero is %s",buf); printf("\nNow the file pointer is at position = %ld", ftell(fp)); fseek(fp, 10, 0);//move to pointer to position 10 printf("\nMove position marker to position 10"); fgets(buf,2, fp); printf("\nThe character at position 5 is %s",buf); printf("\nMove position marker to start of file"); rewind(fp);//move file pointer to start of file printf("\nNow the file pointer is at the start of the file = %ld", ftell(fp)); fgets(buf,2, fp); printf("\nThe current character is = %s", buf); fclose(fp); return 0; }
Detecting the End of a File
There are two ways to detect end-of-file.
Detecting EOF character – When a character input function reads the EOF this indicates the end of the file
Checking FEOF character – The function feof() returns 0 if the end of file fp hasn’t been reached, or a nonzero value if end-of-file has been reached.
File Management Functions
Deleting a File
To delete a file use the function remove(). The prototype is
int remove( const char *filename );
The variable *filename is a pointer to the file name to be deleted. If the file exists, it is deleted and the remove function returns 0. If the user does not have sufficient access rights, or the file does not exist or is already open then the delete operation will fail returning -1.
Renaming a File
The rename() function changes the name of an existing disk file. The prototype is
int rename( const char *oldname, const char *newname );
The function returns 0 on success, or -1 if an error occurs. For the function to work the old filename must exist and the new filename must not exist. Both files must be on the same disk.
Temporary file names
A temporary file is a file that is created and used by the program during program execution and then deleted before the program terminates. The function tmpnam() returns a string containing a unique file name suitable to safely use without risking overwriting any existing files. The prototype is as follows:
char *tmpnam(char *f);
The parameter f must be a pointer to a buffer large enough to hold the filename. A null pointer ( NULL ), means the temporary name is stored in the tmpnam() buffer. The function returns a pointer to that buffer.
#include <stdlib.h> #include <stdio.h> int main() { char temp[20]; tmpnam(temp);// create temporary name and store in temp buffer printf("Temporary name: %s", temp); return 0; }