Files I/O in C Programming

Introduction to files

When we write any program, it will have certain inputs and outputs. So far we have seen programs accepting inputs from users who are entering the values for specific requirements. These inputs were like entering 2 numbers for arithmetic operation, student detail, or any other details where program will ask to enter list of inputs using keyboards. Here we had very limited set of inputs. These entered inputs are lost once the program is over. If we have to re-execute the program for the same input, then we have to re-enter all the input values.

But when we write a code for real world scenarios, these inputs might not be limited. We might need to run the program several times in day or week or month for the same input. But if user has to enter these input values, it is simply a waste of time. For this reason, if we store these input values in a file and if program itself can read the file, then our job is just to execute the program. The program itself will manage to read the input files for required inputs and give us the results.

Similarly, when we run the program with regular input/ output methods, it will display the result in a screen. This will be good as far as our program is limited to one user. But when a program is written to generate reports or so, we will see the reports when we execute the program. But if we want to see the report again, then we have to re-execute it and we will see it on screen. This report will vanish away as soon as program is over or when we close the window. If we get these reports in a file, we can re-visit them whenever we want to see it. We need not re-execute the program every time we want to see the reports.

All these requirement of the user lead C programs to read from the file and write into the file. These files can be a simple text file with tab delimited or comma separated or with any other delimiter. We can also have binary files stored in binary format to have larger number of inputs/outputs to get stored. For smaller data, we use text files and for larger number of data we use binary files. But both are accessed in similar way except small difference. Let us see how to create and access the files using C programs below.

Open a File

When we write a program for storing the data, we have to create a file. We can even access existing file to write the data. C provides a feature to create a file using its code rather than we manually creating a file. The files either manually created or created by C, can be used for reading and writing.

In C, file is declared as of type FILE. It is defined in the standard input output library stdio.h. Hence we have to include the directive stdio.h in the program. When we create or access the files in C, we need to create a pointer variable of type FILE. This is how a program creates a link between file and the program for the first time.

FILE *fp; // a file pointer used to access a file

This declaration creates a pointer variable of type FILE. But this file pointer is not pointing to any files now. It just creates a memory buffer to hold the file.

Let us now make the file pointer, fp to point to some file. This can be done by using a function fopen ().This function is also defined in stdio.h. The general prototype for fopen function is below:

FILE *fopen (const char * filename, const char * mode);

Where *filename is a file name which needs to be opened for reading or writing. We can specify only file name or full access path of the file.  The *mode is specified is used for indicating the compiler that the file, *filename is opened for reading, writing or both. This file mode can be any one of the following.

 

When we open a file using fopen, it returns pointer to the file which is captured in file pointer of type FILE. If the file cannot be opened or some error occurs, it returns NULL to file pointer. Hence it is always necessary to check for NULL value in file pointer after opening the file. Otherwise it will throw an error while executing the program. It is always advisable to close the files that are opened in the program.  Consider a simple program to open a file in “write” mode. The file that we are trying to write does not exist. Hence it creates a blank file with name “CFileExample.txt”

#include<stdio.h>
void main (){
	FILE *fp; // a file pointer used to access a file

	fp = fopen ("E:\\Cprograms\\CFileExample.txt", "w"); // Opens the file in 'write' mode 
	if (fp != NULL) // fp gets NULL if an error occurs
		printf ("The file 'CFileExample.txt' is opened\n");
	else
		printf ("The file 'CFileExample.txt' is not opened\n");
	fclose (fp); // Closes the opened file
}

Reading from a File

Suppose there is file which has all the student details like their Name, ID, Address, phone, class, marks etc. These information needs to be read from this file into the program as input and a report for each student needs to be generated. This can be done using various file read functions like fgetchar (), fgets () and fscanf (). These functions read the data within the file that has been opened and being pointed by the file pointer.

fgetc ()

This function is similar to getchar () function which is used to read single input character. Here fgetchar () is used to read the data / input from the opened file. The file can be any file like text, excel etc. It reads only one character at a time from the file. It returns the integer value (ASCII value) of the character read from the file. If the file is erroreneous or it could not read the file, it returns EOF.

int fgetc(FILE *fp);

fgets ()

This function reads whole line from the opened file. That means it reads entire words in each line. This function is similar to gets (), but this function reads the data from the file.

char* fgets(char *chrDestStr, int intLength, FILE *fp);

This functions reads one line at a time into chrDestStr which is a string variable. It reads the data from the file pointed by the pointer fp. It reads maximum of intLength -1 characters from the file. But if the line ends with newline character or EOF or ‘\0’, then it stops reading the line there itself rather than reading intLegth-1 characters.

fscanf ()

This is similar to scanf () function used to read the input from the standard input file. Here this function reads the data from the file that is opened. Here we need to specify the datatype of the data that we are reading.

char* fscanf(FILE *fp, const char *format, char *chrDestStr);

This function reads a string value (words) from the file pointer fp, into the string variable chrDestStr. But this chrDestStr can be any datatype – int, float, double, array etc. This is determined by the format string that we use. That means this format string is the one which tells the datatype of the chrDestStr.

#include <stdio.h> 
void main(){
	FILE *fp;
	char chrDest[100];
	errno_t err;

	fp = fopen("E:\\Cprograms\\CFileWrite.txt", "a+"); // Opens the file in 'read' mode
	if (err == 1)
		printf("File is closed\n");
	else
		printf("File is opened for reading\n");

	fscanf_s(fp, "%s", chrDest);
	printf("1.Example of fscanf: %s\n", chrDest);

	fgets(chrDest, 255, (FILE*)fp);
	printf("2.Example of fgets:  %s\n", chrDest);

	printf("3.Example of fgetc:  %s\n", fgetc(fp));

	fclose(fp);
}

Writing to a File

In earlier articles we have seen that outputs are displayed on the screen. If we need to see the output again after sometime, then again we have to execute it. These outputs displayed on the screen cannot be printed too. If we need to see the output for the same set of input again or if we need to take a print of the output, it is always better to have the output in some file. Whenever we want to see the output for which program is already executed once, we can directly open the output file and see it without re-executing the program.

In C, this can be done using different file functions like fputc (), fputs () and fprintf ().

fputc ()

This function is used to write character by character to opened file. Using this function, one can write only one character at a time.

int fputc (int intChar, FILE *fp);

It writes the character value of the argument intChar into the file pointed by the file pointer fp. If this function writes the character into the file successfully, then it returns the same written character; if there is any error, then it returns EOF

fputs ()

This function is similar to puts (). It writes one line at a time into the file. The lines can contain any number of words.

int fputs (const char *chrStr, FILE *fp);

It writes a string value of chrStr into the file pointed by file pointer fp. It returns the non-negative value if the function writes the string into the file; else EOF for any error.

fprintf ()

This function is similar to printf () function. It writes the data into the opened file. This is similar to fputs () function above.

int fprintf(FILE *fp, const char *chrStr);

This function returns non-negative number on success and EOF on any error.

#include<stdio.h>
void main(){
	FILE *fp; // a file pointer used to access a file
	errno_t err;

	fp = fopen("E:\\Cprograms\\CFileWrite.txt", "w+");//Opens the file in write, creates the file if does not exist

	if (fp == NULL){
		printf("Could not open the file CFileWrite.txt' \n");
		exit(0);
	}

	fputc('C', fp); // prints the character to a file
	fputs("\nThis is an example of file write using fputs function", fp);
	fprintf(fp, "\nThis is an example of file write using fprintf\n");
	fclose(fp); // Closes the opened file
}

While executing the program above we can notice that ‘CFileWrite.txt’ was not existing file. It was created by the program, and print function writes the data into the file. We cannot see the output on the screen. It can be viewed only when the file is opened.

Seeking in a File

Suppose we have a data file which contains different student details in each rows. Suppose we have to move the cursor within the file by 100. Then in a normal scenario, we will traverse the cursor by 100 using for loop. But it is a tedious work. In C, it provides a function fseek (), to move the position of the cursor within the opened file.

int fseek(FILE *fp, long offset, int Origin);

It moves offset number of positions of the file pointer within the file from the origin.

fseek (fp, 100, 0);

This moves the cursor to point to 100th record / row in the file from the beginning.

#include<stdio.h>
void main(){
	FILE *fp; // a file pointer used to access a file
	errno_t err;
	char chrDest[100];

	fp = fopen("E:\\Cprograms\\ CFileSeek.txt", "r");

	if (fp == NULL){
		printf("Could not open the file CFileWrite.txt' \\n");
		exit(0);
	}

	fgets(chrDest, 255, (FILE*)fp);
	printf("After fseek, file pointer is at :%s\n", chrDest);

	fseek(fp, 5, 0);// Moves the cursor 5 position

	fgets(chrDest, 255, (FILE*)fp);
	printf("After fseek, file pointer is at :%s\n", chrDest);

	fclose(fp); // Closes the opened file
}

fclose (file_pointer);

It returns zero if the file is closed successfully and if there is any error it returns EOF. When the compiler encounters fclose () function, it writes all the pending data into the file in the secondary memory from the buffer memory, it empties the buffer and releases all those buffer memories and closes the file.

Binary File Input and Output

Binary files are also same as normal files like text or dat, but the content of the file will be stored in binary format in the memory. Hence they are difficult to read by any users like human being. These binary files can be read or processed by binary file processor or programs like C. It provides different functions to read and write binary files.

fread ()

This function is used to read the data from the binary file. This is similar to fscanf () function used in the normal files.

size_t fread (void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *fp);

Here fread reads the data from the file fp. The number of elements and size of the elements to be read are also needs to be specified in the function. It returns the size of the total data read from the file.

#include<stdio.h>
void main(){
	FILE *fp;
	errno_t err;

	struct student {
		int StdId;
		char *StdName;
	}std;

	fp = fopen("E:\\Cprograms\\CFileWrite.txt", "rb");


	if (fp == NULL){
		printf("Could not open the file CFileWrite.txt' \n");
		exit(0);
	}
	printf("Student Details in the file are \n ");
	do{
		fread(&std, sizeof(std), 1, fp);
		printf("%s \n", std.StdName);
	} while (!feof(fp));

 fwrite ()

This function is used to write the data into the file. This is similar to fprintf () function used in the normal files.

size_t fwrite (const void *ptr, size_t size_of_elements, size_t number_of_elements, FILE *a_file);

This function writes specified number of elements with specified size into the file pointed by fp. It returns total size of the data written into the file.

#include<stdio.h>
void main(){
	FILE *fp;
	errno_t err;

	struct student {
		int StdId;
		char *StdName;
	}std;

	fp = fopen("E:\\Cprograms\\CFileWrite.txt", "wb");

	if (fp == NULL){
		printf("Could not open the file CFileWrite.txt' \n");
		exit(0);
	}
	
	std.StdId = 105;
	std.StdName= "Christ";

 	fwrite(&std, sizeof(std), 1, fp);		
	fclose(fp);

}

We can see that the binary file is having some characters which humans cannot read it. We need to use fread function to read the data from this binary file and then we can use printf function to display the read data on the screen.

 

Translate »