Pages

Thursday, December 9, 2010

Random Access in a file

Files in a computer system are accessed in two ways

1. Sequentially : This is the default behavior of the system. Sequential access is the method in which the data of the file is accessed in a serialized way. If the program is to read a file, the data will be read from the first char or byte to the second byte and so on. For example , if the file contains the data "abcdefghi", "a" will be accessed the first, followed by "b", "c" and so on. Similarly if the program is writing the data in the file then it will first write "a", followed by "b","c" and so on. The sequential file access method is fine  for reading a file which will make sense only if the data is read sequentially. The disadvantage of this method is that if you want read a particular portion of the file, you can not jump to a specific point(position) and start reading from there. In the same way, if you want to write data at a particular position you can not do it since sequential access does not allow writing at any random position.

2. Randomly : Random access is the method whereby a file can be read from or written to any position in the file. This method is quite useful where we want to skip some data and read only the desired part. Take the program of any media player for example, when you are watching a movie and you want to move forward some scenes that you have already seen, you can easily move the given "slider" and drop it at the point from where you want to continue watching. This is very useful method during file management because you don't to waste your time and memory in traversing the data that you don't want to see. Random access file handling only accesses the file at the point at which the data should be read or written, rather than having to process it sequentially.

Random File Handling Function

To handle a file randomly the function used are

1. rewind() – The "rewind()" function positions the file pointer at the beginning of the file. It does not matter where the pointer is while using this function. The "rewind()" function will place the pointer to byte no. 0 (beginning) even if it was at the end, middle or anywhere else.
Syntax
    rewind(filepointer);
Example   
    rewind(fp);

2. fseek() – To move to any particular position in a file "fseek()" is used. This function can move the cursor at any desired location.
Syntax
    fseek(file pointer, bytes to move,start position or origin)
 Where    
    file pointer - is the file in which we want to access the data randomly.
    bytes to move - is the number of bytes that we want to move. It is given in "long" format.
    Start Position or origin - The point from where we want to move. It can take the following parameters
        0 - Move from beg. of the file
        1 - Move from the current position
        2 - Move from the end of the file.


    For example if want to move to the 5th byte from the beginning, the "fseek()" function will look like
        fseek(fp,5,0); // 0 denotes that we want to move from the beginning.

        Similarly to move 20 bytes from the beginning, we can use   
        fseek(fp,20,0);

    If we want the movement to happen from the current position of the cursor, we will change the third argument to 1
        fseek(fp,10,1); // Will move 10 bytes forward from the current position.
    to move backwards, the second argument will a negative number

        fseek(fp,-30,1) ;// Will move 30 bytes backwards from the current position

    To move from the end, we will write 2 as the third argument, while the second argument will be a negative number.
        fseek(fp,-25,2);//Will move 25 bytes backwards from the end of the file

    As you can see, when we are moving from the beginning of the file, the second argument should be a positive number since you can not move backwards from the beginning of the file. In the same way if you are making a move from the end, the second argument will always be a negative number since you can not move forward from the end. The only exception is while moving from the current position. While moving from the current position you can write both positive and negative values since you can make a move in both the directions.   
3. ftell() – If we want to check the current offset (cursor) position in a file, we can use the "ftell()" function. This function returns the current position of the cursor.
Syntax
    int ftell(filepointer);
Example
    int pos;
    pos=ftell(fp);

   
    If the "ftell()" function is applied right after opening the file, it will return 0 since we haven't read the data or used the "fseek()" function.

Wednesday, December 8, 2010

Reading Binary Files

Let's try to read the files we created in previous articles using "fwrite()", function. As I told you, you can not read or open a file written using "fwrite()" by any method other than using the "fread() function. The syntax of "fread()" is similar to the "fwrite()" function. fread( ) function causes the data read from the disk to be placed in the structure variable specified within the syntax. The function "fread()" returns the number of records read. Ordinarily, this should correspond to the third argument, the number of records we asked for... 1 in this case. When there are no more records to be read means we have reached the end of file, since fread() cannot read anything, it returns a 0. By testing for this situation, we know when to stop reading.So let's see how a binary file will be read. We will be reading the same files one by one.

Example 1 : Reading the "list" file , created in example 1 in the previous post

#include
#include
struct person
{
char name[12];
int age;
};


void main()
{
clrscr();
FILE *fp;
fp=fopen("list","w");
person p;
printf("\nEnter name ");
scanf("%s",&p.name);
printf("\nEnter age ");
scanf("%d",&p.age);
fwrite(&p,sizeof(person),1,fp);
printf("\n1 person added");
fclose(fp);
// Reading starts from here
fp=fopen("list","r");
fread(&p,sizeof(person)1,fp); // reading the data using the fread() function
printf("\nHere is the data entered in the file...");
printf("\nName : %s",p.name);
printf("\nAge : %d",p.age);
fclose(fp);
}

Description
The writing part is same as given earlier. When it comes to reading the file, the "fread()" reads the data of the file(name and age) and stores it to the object "p". When we print the values of "p.name" and "p.age", it will print the data which was there in the file. How does "fread()" know how many records to read? There are two things to remember before answering this question, first - since we have written "fread()" just once, it will perform the read operation just once, and secondly "fread()" does not read records, it reads "bytes". How many bytes constitue a record has been informed to it by using the "sizeof" operator. We are telling the "fread()" function to read "sizeof" amount of bytes from the file. In this example the size of one record is 14 bytes (12 bytes for name,2 bytes for age), therefore the "fread()" function will read the first 14 bytes from the file. The first bytes will form the data of the first person.


Example 2 : Reading the "library.dat" file, created in example 2 in the previous post.
#include
#include
struct books
{
int bookno,price;
char name[12],pub[20];
};
void main()
{
clrscr();
char c;
FILE *fp;
fp=fopen("library.dat","a");
books b;
do
{
printf("\nBook no ");
scanf("%d",&b.bookno);
fflush(stdin);
printf("\nEnter book name ");
gets(b.name);
printf("\nEnter publisher ");
gets(b.pub);
printf("\nEnter book price ");
scanf("%d",&b.price);
fwrite(&b,sizeof(books),1,fp);
fflush(stdin);
printf("\nNew book added to library.");
printf("\nPress Y to add more books, N to Close : ");
scanf("%c",&c);
}while(c=='Y' || c=='y');
fclose(fp);
fp=fopen("library.dat","r");
while(fread(&b,sizeof(books),1,fp)==1) // reading book data one record at a time
{
printf("\nBook no %d",b.bookno);
printf("\nBook name %s",b.name);
printf("\nPublisher %s",b.pub);
printf("\nPrice %d",b.price);
printf("\n-----------------------------------"); // Just a seperator, two differntiate between 2 records optional)
}
fclose(fp);
}

Description
Since there are multiple records in this file and we don't know how many records have been entered by the user, we'll to put the "fread()" function inside a while loop. Remember that fread returns 1 if it finds data in the file and 0 if there is no data to be read, therefore we have written the condition "while(fread)==1", so that the loop continues to read the data till the end of the file. When all the data has been read, the "fread()" function will return 0 and the loop will terminate. All the records are printed by one by one with an optional seperator between each record.


Example 3 - Reading the "school" file, created in example 3 in the previous post.

#include
#include
struct student
{
int rollno,marks1,marks2,marks3,total,avg;
char name[10];
};
void main()
{
student s;
FILE *fptr;
fptr=fopen("school","a");
char ch;
int i;
for(i=0;i<5;i++)
{
printf("\nRollno ");
scanf("%s",&s.rollno);
printf("\nName ");
scanf("%s",&s.name);
printf("\nMarks 1 ");
scanf("%d",&s.marks1);
printf("\nMarks 2 ");
scanf("%d",&s.marks2);
printf("\nMarks 3 ");
scanf("%d",&s.marks3);
s.total=s.marks1+s.marks2+s.marks3;
s.avg=s.total/3;
fwrite(&s,sizeof(student),1,fptr);
printf("\nSaved in the file");
}
fclose(fptr);
fptr=fopen("school","r");
while(fread(&s,sizeof(student),1,fptr)==1)
{
printf("\nRollno %d",s.rollno);
printf("\nName %s",s.name);
printf("\nMarks 1 %d",s.marks1);
printf("\nMarks 2 %d",s.marks2);
printf("\nMarks 3 %d",s.marks3);
printf("\nTotal marks %d",s.total);
printf("\nAverage %d",s.avg);
printf("\nPress any key to continue ...");
getch();
}
fclose(fp);
}


Description
The reading process is same as that of example 2. Here we have added an "Press any key" message also so that the user can pause the screen after each record.

Writing a file in binary mode

To write a binary file the function that we will use is "fwrite()".  The "fwrite()" function can write binary data to a file.

Syntax
    fwrite(&data,sizeof_data,no_of_rec,filepointer)
   
Here, the first argument is the address of the structure or variable which we want to write to the file. The second argument is the size of the structure in bytes. We can calculate the size manually(int 2 byes, float etc), but this approach is not recommended since the size of data type depends on the processor.  Therefore instead of calculating it ourselves, we use the "sizeof()" operator to do the same. The sizeof( ) operator gives the size of the variable in bytes. This will help us in 2 ways - first, we won't have to perform  the calculations manually, and secondly if the datatype of the data to be written is changed, we don't need to make changes in the program.The third argument is the number of such structures that we want to write at one time. In this case, we want to write only one structure at a time. Had we had an array of structures, for example, we might have wanted to write the entire array at once.The last argument is the pointer to the file we want to write to.


Example 1 : Writing a record to a file

#include
#include
struct person
{
    char name[12];
    int age;
};
void main()
{
    clrscr();
    FILE *fp;
    fp=fopen("list","w");
    person p;
    printf("\nEnter name ");
    scanf("%s",&p.name);
    printf("\nEnter age ");
    scanf("%d",&p.age);
    fwrite(&p,sizeof(person),1,fp);
    printf("\n1 person added");
    fclose(fp);
}

Description

The above program is a basic example of how the data of a structure(record) can be saved to a file. The program starts with a structure declaration with two member variables, name and age. In main, we have created an object of the structure "person" with the name "p". If you remember, we can not access the structure variables directly. We must create an object to access all the members using the "objectname.membername" notation, for example "p.name". When all the values have been entered by the user, we will not write "name" and "age" in the file separtely since both of them are inside the object "p". If we can somehow write the value of "p" in the file both "name" and "age" will be saved.
To save the data in binary format the function "fwrite()" has been used. "fwrite()" has been given 4 arguments.
  • First argument (&p) : is the address of the object that has to be saved in the file. It will contain all the values that were present in the structure.
  • Second argument (sizeof(person)) : is the size of memory that will be required to save this data. The "sizeof" operator will automatically calculate the memory occupied by the structure.
  •     Third argument (1) : is the number of structures that we want to write. Since we want to write only one structure at time 1 is written.
  •     Fourth argument (fp) : is the file pointer in which we want to store the data.


After running this program, try to read the file "list" using any method. You will see that the data printed will not be readable. Why is it so? because the file has been written the using the binary function "fwrite()". The data has been written in binary format which can not be read directly. We will learn about reading such files later.

Example 2 : Writing multiple records to a file

#include
#include
struct books
{
    int bookno,price;
    char name[12],pub[20];
};
void main()
{
    clrscr();
    char c;
    FILE *fp;
    fp=fopen("library.dat","a");
    books b;
    do
    {
    printf("\nBook no ");
    scanf("%d",&b.bookno);
    fflush(stdin);
    printf("\nEnter book name ");
    gets(b.name);
    printf("\nEnter publisher ");
    gets(b.pub);
    printf("\nEnter book price ");
    scanf("%d",&b.price);
    fwrite(&b,sizeof(books),1,fp);
    fflush(stdin);
    printf("\nNew book added to library.");
    printf("\nPress Y to add more books, N to Close : ");
    scanf("%c",&c);
    }while(c=='Y' || c=='y');
    fclose(fp);
}


Description
    Logically, this program is similar to the previous "person" program. The only new thing we have done here is that we have written the "fwrite()" function inside the loop. This will allow the user to enter as many records as needed.


Till now what we have written to the files is entered by ther user himself. Sometimes, there can be a condition that we want to accept some data from the user and some values are to be calculated.Let's make a program to do so.
Example 3 - Writing calculated values to the file

#include
#include
struct student
{
    int rollno,marks1,marks2,marks3,total,avg;
    char name[10];
};
void main()
{
    student s;
    FILE *fptr;
    fptr=fopen("school","a");
    char ch;
    for(int i=0;i<5;i++)
    {
        printf("\nRollno ");
        scanf("%s",&s.rollno);
        printf("\nName ");
        scanf("%s",&s.name);
        printf("\nMarks 1 ");
        scanf("%d",&s.marks1);
        printf("\nMarks 2 ");
        scanf("%d",&s.marks2);
        printf("\nMarks 3 ");
        scanf("%d",&s.marks3);
        s.total=s.marks1+s.marks2+s.marks3;
        s.avg=s.total/3;
        fwrite(&s,sizeof(student),1,fptr);
        printf("\nSaved in the file");
    }
    fclose(fptr);
}


Description
In this program we are writing the data of 5 students using a for loop. A student record has 7 values rollno,name,marks1,marks2,marks3,total and average. Out of these 7 values, 5 are being entered by the user and 2 are being calculated by the program. Total is calculated by adding all three marks, whereas avg has been achieved by dividing the total by 3. When we write the data using "fwrite()", we are writing the value of "s" which has 7 values in total, 5 entered by the user and 2 calculated values. In this way we can store customized values to the file.

Monday, December 6, 2010

Text and a Binary file

As mentioned earlier files are required to store information permanently for future use. The files can be stored in two ways

1. Text Files : Text Files store information in ASCII codes. In text files, each line of the text ends with a special character known as the "End of Line" character (EOL).

2. Binary Files : A binary file is just a file that contains information in the same format in which the information is held in memory. In binary file, there is no delimiter for a line. Also no translations occur in binary files. As a result, binary files are faster and easier for program to read and write than text files. If the file is not needed to be read by a person directly, binary file are the best way to store program information. A binary file is a file of any length that holds bytes with values in the range 0 to 0xff. (0 to 255). These bytes have no other meaning unlike in a text file where a value of 13 means carriage return, 10 means line feed, 26 means end of file and software reading text files has to deal with these. In modern terms we call binary files a stream of bytes and more modern languages tend to work with streams rather than files.How would you know that a file is a text file or a binary file? It's simple. Just try to open the file in any editor like "Notepad" in Windows. If the file opens successfully and you can read the data easily, it's a text file otherwise a binary file.

Difference between a text and a binary file

1. A text file can be easily opened in an editor, whereas a binary file can not be.In C, when you create a binary file you can't read it in the normal way. This means that if a file was created using binary writing function you won't be able to open it using DOS Shell or the File -> open methods (given in the previous posts). Then how would you read such a file? The only method to read a binary file is by creating a program for "Binary Reading".
2. In text files, a special character whose ASCII value is 26 is automatically added to the end of the file. This mark is called the end of file (EOF) marker. When we create a program to read a text based file, it is this symbol which is searched. As soon as this symbol is reached "end of file" is assumed. Opposite to this in binary files, the size of the file is determined from the file's entry in the OS's directory and file table. If a file has been written in text mode it should be read in text mode only. Similarly if a file was created in binary mode, the same should be used for reading.
3. In text mode, a newline character ("\n") is converted into the carriage return-linefeed combination before writing it to the disk. Similarly, the carriage return-linefeed combination on the disk is converted back into a newline when the file is read in text mode. But, if a file is opened in binary mode these conversions will not take place.
4. In text mode, to write numbers in a file, the function available is "fprintf()". The "fprintf()" function stores numbers as string rather that integers. Therefore if you write the values 19567which would have taken 2 bytes as integer will take 5 bytes if written through "fprintf()". This means more memory will be required to even more large numbers. Contrary to this binary functions store data in binary mode which consumes the same amount of disk space as it does in memory.

A data entry program

A data entry program which reads and writes the data using different functions.

#include
#include
#include
FILE *fp; // public variable fp. It can now be accessed in all the functions of the program.
void main()
{
    clrscr();
    void write();
    void read();
    int c;
    do
    {
        printf("\n C O M P U T E R -- Q U I Z ");
        printf("\n ===========================");
        printf("\n1. New Test");
        printf("\n2. List of appeared candidates");
        printf("\n3. Exit");
        printf("\nSelect an option ");
        scanf("%d",&c);
        if(c==1)
            write();
        else if(c==2)
            read();
    }while(c!=3); // Run till the user enters 3 to exit the program.
}
void write()
{

    int marks=0,c;
    char name[10],doe[10],result[12],choice;
    fp=fopen("exam.txt","a");
    do
    {
        clrscr();
        printf("\nCandidate Details");
        printf("\n-----------------");
        printf("\n\nCandidate Name : ");
        scanf("%s",&name);
        printf("\nDate of exam : ");
        scanf("%s",&doe);
        printf("\nPress any key to start the quiz..");
        getch(); // to pause the screen
        clrscr();
        printf("\nQ1. What is the full form of CPU ? ");
        printf("\n1. Central Processing Unit 2. Central Power Unit");
        printf("\nEnter your choice ");
        scanf("%d",&c);
        if(c==1)
            marks+=10;
        printf("\nPress any key for the next question ...");
        getch();
        clrscr();
        printf("\nQ2. Which of the following is a temporary memory ? ");
        printf("\n1. ROM  2. RAM");
        printf("\nEnter your choice ");
        scanf("%d",&c);
        if(c==2)
            marks+=10;
        printf("\nPress any key for the next question ...");
        getch();
        clrscr();
        printf("\nQ3. Which company makes Windows ? ");
        printf("\n1. Oracle Corp. 2. Microsoft Corp.");
        printf("\nEnter your choice ");
        scanf("%d",&c);
        if(c==2)
            marks+=10;
        printf("\nPress any key for the next question ...");
            getch();
        clrscr();
        printf("\nQ4. Which of the following is not an Operating System ? ");
        printf("\n1. Java           2. Linux");
        printf("\nEnter your choice ");
        scanf("%d",&c);
        if(c==1)
            marks+=10;
        printf("\nPress any key for the next question ...");
        getch();
        clrscr();
        printf("\nQ5. Which of the following is an Object Oriented Language ? ");
        printf("\n1. C++         2. C");
        printf("\nEnter your choice ");
        scanf("%d",&c);
        if(c==1)
            marks+=10;
        printf("\nPress any key to finish the quiz ...");
            getch();
        clrscr();
        printf("\n Finished");
        // Result is determined as per the marks scored.
        if(marks>=0 && marks<=20)
            strcpy(result,"Fail");
        else if(marks>=30 && marks<=40)
            strcpy(result,"Good");
        else
            strcpy(result,"Excellent");
        // Writing the data to the file exam.txt
        fputs("\nName ",fp); // Writing the heading first
        fputs(name,fp); // Writing the value of name
        fputs("\nExam Date ",fp);
        fputs(doe,fp);
        fputs("\nResult ",fp);
        fputs(result,fp);
        fclose(fp);
        fflush(stdin);
        printf("\nDo you want to conduct another test ? ");
        scanf("%c",&choice);
    }while(choice=='y'|| choice=='Y');

}
void read()
{
    char line[15];
    fp=fopen("exam.txt","r");
    clrscr();
    printf("\nList of appeared candidates");
    printf("\n===============================");
    while(fgets(line,15,fp)!=NULL)
    {
        printf("%s",line);
    }
    fclose(fp);
    printf("\nPress any key to return to main menu ...");
    getch();
}

Description
This is a basic computer quiz program. The program contains two functions namely write and read. The write function is used to write the candidate's details like name, date of exam etc. and saves them in the file. In main, we have asked the user to enter his choice - 1 for writing (taking the quiz) and 2 for reading (printing details of the appeared candidates). 
The "Write" function
    The write function opens the file in "a" mode which means "append" mode. The "append" mode denotes that we want to write the details of all the candidates in the file one after the other without overwriting the previous data. If we use "w" mode in place of "a", it will overwrite the details of the previous candidates. Inside the function we are asking the user some basic questions. Each question has 2 options out of which the user has to choose the correct one. For each correct answer we are assigning 10 marks to the candidate by writing "marks+=10" after each question. Once all the questions have been answered, the total marks are calculated. "Result" is determined as per the result, "Excellent" for those who have scored full (50) marks and "Fail" for those who haven't given a single correct answer After the completion of the test, all the details which were entered by the user are saved in the file along with the result. Note that while writing the details we have used two "fputs()" per value.
This has been done to save the data along with its heading. For example to write the value of "name", the first "fputs()" first writes "Name" as a heading after which the second "fputs()" writes the value of the variable "name". Similarly "doe" has been saved under the heading "Exam Date" and so on. The benefit of using double "fputs()" will be shown while reading the file, where each value will come after the heading. Like "Name Xyz","Exam Date 2-10-2010" etc.  You can easily skip the heading part if you want.The loop will ask the user to confirm whether he wants to continue or not. If the user chooses "y" the loop will run again, asking the user details again and quiz starts again. The details of each of the candidates will be saved in the file.
The "Read" function
    The read function will print the details of all the candidates who have taken the test. It opens the file in "read" mode and starts printing the details using "fgets()" reading 15 bytes at a time. This will print all the contents of the file. The file is closed and the user is asked to press a key to continue.

More file handling examples

Let's make some more programs involving file handling functions. The first program is for copying a file to another. In this program we are going to make a change, instead of "hard coding"  the file name, we will ask the user to enter the name of the files. This will give user the option to change the file names every time the program is run.

Example 1 : Copying a file : Char by Char

#include
#include
void main()
{
    clrscr(); // Line 1
    FILE *fp1,*fp2; // Line 2
    char src[12],target[12]; // Line 3
    char c; // Line 4
    int cnt=0; // Line 5
    printf("\nEnter source file name "); // Line 6
    scanf("%s",&src); // Line 7
    fp1=fopen(src,"r"); // Line 8
    if(fp1!=NULL) // Line 9
    { // Line 10
        printf("\nEnter new file name "); // Line 11
        scanf("%s",&target); // Line 12
        fp2=fopen(target,"w"); // Line 13
        c=fgetc(fp1); // Line 14
        while(c!=EOF) // Line 15
        {         // Line 16
            fputc(c,fp2); // Line 17
            cnt++; // Line 18
            c=fgetc(fp1); // Line 19
        }        // Line 20
        printf("\nSuccessfully copied %d chars to %s",cnt,target); // Line 21
        fclose(fp1); // Line 22
        fclose(fp2); // Line 23
    }            // Line 24
    else            // Line 25
        printf("\nSource file does not exists"); // Line 26
}    // Line 27


Description
Line 2 :
    Declares 2 FILE pointers one to hold the source file and second for the target file.
Line 3:
    Declares 2 strings named "src" and "target", one to contain the source file name and the other for the target file name.
Line 6 and Line 7 :
    Asks the user to enter the name of the file to be copied.
Line 8 :
    In this line, the function "fopen()" has been passed two arguments. The first argument is the name of the file, which in this case is the name entered by the user in line no. 6 and 7. Since the file name is saved in the variable "src", this is the first argument. Don't put src in double quotes (" ") because doing this will make C think the name of the source file is "src", which is not the case. "src" is not the name of the file, but the name of the variable which has the source file name. The second argument is the "read" mode since this file will be opened in read mode.
Line 9 :
    It is possible that the file name entered by the user is not available. In such a case the value of the variable "fp1" will be NULL. The line no. 9 checks if the value of fp is NULL. If it is then the control will move directly to line no. 24 citing that the "Source file does not exists".
Line 11 and Line 12 :
    It the source file exists, the program asks for the target file name. It can be the name of any new file. If there is no file with this name, the program will make a new one. If there is a file it will be overwritten.
Line 13:
    The target file is opened in the "write" mode in the pointer "fp2" because we have to write(copy) data in it.
Line 14:
    The first character of the source file is read and stored in the variable "c".
Line 15:
    Since "c" is not equal to EOF, the program enters the loop.
Line 17:
    To write the data to another file, the "fputc()" function has been used to write the same char to the second file pointer, "fp2".  If the first char which was read at line no. 14 was "H", it will be written to the target file.
Line 18:
    The variable "cnt" is incremented by 1 so that we can print the number of characters copied at the end.
Line 19:
    Once the first character is written to the target file, we move on to read the second character. The loop will continue the statements given in the line no. 17 to 19 till all the character of the source file are written to the target file. On one hand we are reading from the source file and on the other hand we are writing the same to
the target file.
Line 21:
    After copying the file the value of "cnt" has been printed to let the user know how many character were copied.
Line 22 and Line 23
    Both file are closed to release memory.

Example 2 : Converting a file to upper case in the target file

#include
#include
#include
void main()
{
    clrscr();
    FILE *fp1,*fp2;
    char src[12],target[12];
    char c;
    int cnt=0;
    printf("\nEnter source file name ");
    scanf("%s",&src);
    fp1=fopen(src,"r");
    if(fp1!=NULL)
    {
        printf("\nEnter new file name ");
        scanf("%s",&target);
        fp2=fopen(target,"w");
        c=fgetc(fp1);
        while(c!=EOF)
        {
            fputc(toupper(c),fp2); // Line No. 17
            cnt++;
            c=fgetc(fp1);
        }
        printf("\n Successfully copied %d chars to %s",cnt,target);
    }
    else
        printf("\nSource file does not exists");
}

Description
The above program is same as the previous example, a minor difference is at line 17 where before writing the data to the target file we have converted the char to upper case. This will create the resultant file in capital letters. To use the "fputc()" we have included the header file "".

Example 3 : Copying a file String by String

#include
#include
void main()
{
    clrscr(); // Line 1
    FILE *fp1,*fp2; // Line 2
    char src[12],target[12]; // Line 3
    char str[12]; // Line 4
    printf("\nEnter source file name "); // Line 5
    scanf("%s",&src); // Line 6
    fp1=fopen(src,"r"); // Line 7
    if(fp1!=NULL) // Line 8
    {        // Line 9
        printf("\nEnter new file name "); // Line 10
        scanf("%s",&target); // Line 11
        fp2=fopen(target,"w"); // Line 12
        while(fgets(str,12,fp1)!=NULL) // Line 13
        {            // Line 14
            fputs(str,fp2); // Line 15
        } // Line 16
        printf("\nSuccessfully copied"); // Line 17
    }            // Line 18
    else            // Line 19
        printf("\nSource file does not exists"); // Line 20
}


Description
    Same program is created again, with the "fgets()", "fputs()" function. The "fgets()" inside the loop reads 12 chars at a time, copies them to the target file using "fputs()". The program continues till the end of the source file.

File Modes - Reading and Writing Files

File Modes - Reading and Writing Files
In a file handling program we must specify why and how we want to open it. In other words we must specify whether we want to create a new file, or are we overwriting an existing file, or we want to append data in an existing file. To specify it we must use different modes which are provided by C. These modes are usually in single letter like "r", "b", "w", "a". Sometimes a "+" is also used with these modes to provide some additional functionality.
  • The "r" mode - Opens the file for reading. This fails if the file does not exist or cannot be found. The file to be read must be an existing file.
  • "w" - Opens the file as an empty file for writing. If the file exists, its contents are destroyed.
  •  "a" - Opens the file for writing at the end of the file (appending) without deleting its existing contents. If the file is not existing, this mode can create a new file also.

A "+" sign can also be used with these mode to make them even more useful.

  • "r+" Opens the file for both reading and writing. (The file must exist.)
  • "w+" Opens the file as an empty file for both reading and writing. If the file exists, its contents are destroyed.
  • "a+" Opens the file for reading and appending; the appending operation includes the removal of the EOF marker before new data is written to the file and the EOF marker is restored after writing is complete; creates the file first if it doesn't exist.
Following is the list of various modes in which we can handle a file.

Mode           Type of file     Read Write         Create            Truncate
  1. r          text                    Read
  2. rb+      binary                Read
  3. r+        text                    Read Write
  4. r+b      binary                Read Write
  5. rb+      binary                Read Write
  6. w         text                   Write                   Create                Truncate
  7. wb       binary               Write                   Create                Truncate
  8. w+       text                   Read Write           Create                Truncate
  9. w+b     binary               Read Write           Create                Truncate
  10. wb+     binary               Read Write           Create                Truncate
  11. a          text                   Write                    Create
  12. ab        binary               Write                    Create
  13. a+         text                  Read Write          Create
  14. a+b         binary            Write                   Create
  15. ab+         binary            Write                   Create