Today we are going to discuss FILE SYSTEM operations using the C language. Till now we have worked with the RAM for storing our variables and our data. But the RAM is not persistent. We need to store data permanently. So we store them in permanent memory like hard disks or CDs/DVDs, in files. Different types of data are stored in different type of files, but for our purposes we’ll work with text files in windows system which have an extension of ‘.txt‘.
We’ll learn how to store characters in a file and read characters from an existing file. To interact with files we have another pointer type of FILE pointer. It points to the first byte of the file. Let us see how to read and write files.
In this program, we create a text file for windows system (.txt) and write to it whatever the user enters through the terminal/command prompt. First we create a file-pointer fp. We create a file called new.txt using the fopen() function and indicate we are going to write into it by the “w” flag as the second argument of the fopen function. This function returns a file pointer that points to the first character of the file, so we assign it to fp. We also create a char variable ch to read/write a character from/into the file.
The user-input is read by a function called getchar() (line no.9 in the program). Getchar is a function in C programming language that reads a single character from the standard input stream stdin, regardless of what it is, and returns it to the program. It is included in the stdio.h header file.
To stop reading from the terminal, we prompt the user to manually enter the End of File character, which is control+z in windows. In the while loop (line no.9), it checks whether the input character read is the EOF character, and if not, it writes the character to the file using the putc() function. The putc function takes a single character as the first argument and the file pointer as the second argument and then writes the character into the file.
When the getchar function encounters the EOF, it breaks out of the while loop, the the file is closed with the fclose() function.
At this point we can check the file in our hard disk to confirm whether the user input is correctly written in the file.
In line no.16 we again open the file, but this time with the flag “r” which indicates we are opening it to read only. Then using another while loop, we read characters from the file, one by one with the getc() function, and assign the returned value to the variable ch. We check whether it is the EOF character, and if not, we print it to the screen. When we encounter EOF we break out of the while loop and then close the file and terminate the program.
Now that we have the basic idea of how to read and write files, lets see a practical use case. As we see in any operating system with a graphical user interface (like windows/mac/linux), we can right-click and copy a file and navigate to another location in our hard disk and right-click and paste the file there. But under the hood, some code in the operating system handles this operation. It reads the file, loading some number of bytes/kilobytes at a time in the RAM, and writes that chunk into the new file in the hard disk. It repeats this process until the whole file is copied. As the unix OS is written in C, lets see how we can copy a file from one location in the hard disk and paste it in another location, using a C program.
In this program, we’ll use the parameters in the main() function to pass the source and destination paths for the file. We pass the paths as strings separated by spaces. For a detailed explanation about passing arguments to main function, refer this blog.
In the main function, the first parameter is the count of strings passed as arguments. By default the path to the program itself in the hard disk is the first argument. So when we pass the source and destination paths, the total number of arguments will be 3. We check this in line no.4 and exit out early if the number of arguments doesn’t match.
Then we save the source and destination paths in string variables source and destination. We create file pointers fs and fd to operate on the source and destination files. Instead of reading/writing one byte at a time, we take a more practical approach, where we read/write in chunks of characters by storing them in the RAM in a char array. Generally this is called a buffer, so we create a char array of 40 characters and name it buffer. We also create a char pointer checkEOF, which we will use to check for NULL pointer, which is returned when the file has no more characters to read and fgets() function, which we use to read strings from a file, returns a NULL pointer.
We open the source file with the “r” flag and the destination file with the “w” flag, which also creates the file if it doesn’t exist. In case any of the pointers returned by the fopen functions return a NULL pointer, we exit out of the program with an error message.
Using the fgets() function we read 40 characters from the file, pointed by fs pointer and store it in the buffer variable. This function also returns a pointer which we store in checkEOF to check for NULL pointers, in a while loop, to determine if the file has no more characters to read. Inside the while loop we write this buffer into the destination file using the fputs() function and read the next chunk from the source and repeat the process.
After the whole file is copied to the file newly created in the destination path, we exit out of the while loop and close both the files.
Note: The command to run the program, i.e.
./file-ops C:\\Users\\Sudipta\\Desktop\\cprogs\\structures.txt C:\\Users\\Sudipta\\Desktop\\copied.txt
has two backslashes after every folder name. This is because ‘\’ is a special character and we have to escape it with another ‘\’.
With this topic, we have finally come to the end of basics of C programming expected to be taught in a beginner’s course. From the next blog our topic of discussion will be broader and will cover other programming languages too.
You can download the code here.
If you liked this article please comment and show your support and interest so that I’ll be motivated to continue this effort. Like our facebook page if you haven’t already. And if you have any questions please comment. I’ll try to reply all.