Understanding Advance File Handling Functions in C

Discussion in 'C' started by poornaMoksha, Nov 30, 2011.

  1. Continuing my previous article Understanding File Handling Functions in C, here in this article let us focus on functions like :

    fread() // read a chunk of data from file
    fwrite() // Write a chunk of data to file
    feof() // Check for end of file indicator
    ferror() // Check for error indicator for this stream
    fseek() // Seek to a particular position in file
    fileno() // Return an integer file descriptor
    fdopen() // associate a stream with existing file descriptor

    Lets understand these functions in two sets.

    Understanding fread(), fwrite(), feof() and ferror()



    Here is a code that uses the above three functions :

    Code:
    #include<stdio.h>
    #include<string.h>
    
    int main(void)
    {
        FILE *fd = NULL;
        char buff[512];
        unsigned int nread = 0;
    
        memset(buff, '\0', sizeof(buff));
    
        // Open a file 'ps.txt' in r+ mode ie a mode that 
        // supports both reading and writing.
        fd = fopen("ps.txt","r+");
        if(NULL == fd) // Check for error
        {
            printf("\n File opening failed\n");
            return 1;
        }
        nread = 50; // Hard code the number of elements to 50
    
        // fread() reads 'nread' elements of data, each being 1 byte long
        // from 'fd' file descriptor and copies the chink of data read 
        // from file to the buffer 'buff'.
        // It returns number of items successfully read, like in this case
        // if the call is successful, it should return the value of 'nread'.
        // So, here we have tested the return of this function against the 
        // 'nread' variable to judge whether the API failed or passed.  
        while( nread == fread(buff, 1, nread, fd) )
        {
            printf("\n THE %d BYTES READ ARE :  \n<<<%s>>>\n\n\n", (int)nread, buff);
        }
    
        // This function is used to test the end of file indicator for a file
        // What happens is that, through any kind of read operation in the file
        // if we try to read past the end of file then end-of-file indicator is
        // set. After this anytime if we call feof(), it will return a non-zero 
        // value signifying that end of file has been reached. If this API returns
        // zero then that means end of file has not yet been reached. NOTE that 
        // this API works only if a read attempt past the end of file has been made
        // For example, for a 50 byte file, merely reading all the 50 bytes will not
        // set the end-of-file indicator. An attempt to read past should have been 
        // made before making a call to feof(). This function takes file descriptor
        // as an argument.
        if(feof(fd))
        {
           printf("\n Seems like end of file was reached\n");
        }
        // IF while performing any type of file related operations using file related
        // functions, an error occurs then error indicator is set. This error indicator
        // can be examined by this function so that code may come to know that an error
        // has occurred. This function also takes file descriptor as an argument. 
        else if(ferror(fd))
        {
           printf("\n Some errors on this stream occurred\n");
        }
         
        // Reset the buffer with NULLs
        memset(buff, '\0', sizeof(buff));
        // Copy a hard coded string to buff so that we can write this string in file.
        strncpy(buff, "SomeThing to be written to file\n", strlen("SomeThing to be written to file\n"));
    
        // fwrite() is used to write a chunk of data to file. To be specific, it writes 
        // 1 element of size return by strlen() from 'buff' to the file using file 
        // descriptor 'fd'. As fread(), this function also returns the number of items
        // successfully written, which in this case is '1'.
        if(1 == fwrite(buff, strlen("SomeThing to be written to file\n"), 1, fd))
        {
            printf("\n File written successfully\n");
        }
        else
        {
            printf("\n File writing failed through fwrite()\n");
            return 1;
        }
    
        return 0;
    }
    The code above is self explained. I have written all the explanations as comments in the code so that whosoever copies the code for practice, automatically takes away the explanation part too.

    Now lets see the output


    Output



    Before looking at the output, lets look at the ps.txt first :

    Code:
    UID        PID  PPID  C STIME TTY          TIME CMD
    root         1     0  0 05:29 ?        00:00:00 /sbin/init
    root         2     0  0 05:29 ?        00:00:00 [kthreadd]
    root         3     2  0 05:29 ?        00:00:00 [migration/0]
    root         4     2  0 05:29 ?        00:00:00 [ksoftirqd/0]
    root         5     2  0 05:29 ?        00:00:00 [watchdog/0]
    root         6     2  0 05:29 ?        00:00:00 [migration/1]
    root         7     2  0 05:29 ?        00:00:00 [ksoftirqd/1]
    root         8     2  0 05:29 ?        00:00:00 [watchdog/1]
    root         9     2  0 05:29 ?        00:00:00 [events/0]
    ...
    ...
    ...
    ...
    himanshu  1993     1  0 05:31 ?        00:00:00 /bin/sh /usr/lib/firefox-3.6.3/firefox
    himanshu  1998  1993  0 05:31 ?        00:00:00 /bin/sh /usr/lib/firefox-3.6.3/run-mozilla.sh /usr/lib/firefox-3.6.3/firefox-bin
    himanshu  2002  1998 20 05:31 ?        00:07:33 /usr/lib/firefox-3.6.3/firefox-bin
    himanshu  2090     1  1 05:34 ?        00:00:29 gedit /home/himanshu/Desktop/articles/go4expert/Nov2011/name_changer.txt
    himanshu  2102  1966  0 05:38 pts/1    00:00:00 bash
    himanshu  2500  1966  2 06:09 pts/0    00:00:00 bash
    himanshu  2515  2102  0 06:09 pts/1    00:00:00 ./namepid
    himanshu  2516  2515  0 06:09 pts/1    00:00:00 sh -c /bin/sh -c 'ps -aef > ps.txt'
    himanshu  2517  2516  0 06:09 pts/1    00:00:00 /bin/sh -c ps -aef > ps.txt
    himanshu  2518  2517  0 06:09 pts/1    00:00:00 ps -aef
    Now when I executed the code, I got :

    Code:
    ...
    ...
    ...
    THE 50 BYTES READ ARE :  
    <<<  2500  1966  2 06:09 pts/0    00:00:00 bash
    himan>>>
    
    
    
     THE 50 BYTES READ ARE :  
    <<<shu  2515  2102  0 06:09 pts/1    00:00:00 ./namep>>>
    
    
    
     THE 50 BYTES READ ARE :  
    <<<id
    himanshu  2516  2515  0 06:09 pts/1    00:00:00>>>
    
    
    
     THE 50 BYTES READ ARE :  
    <<< sh -c /bin/sh -c 'ps -aef > ps.txt'
    himanshu  251>>>
    
    
    
     THE 50 BYTES READ ARE :  
    <<<7  2516  0 06:09 pts/1    00:00:00 /bin/sh -c ps ->>>
    
    
    
     THE 50 BYTES READ ARE :  
    <<<aef > ps.txt
    himanshu  2518  2517  0 06:09 pts/1  >>>
    
    
    
     Seems like end of file was reached
    
     File written successfully
    SO we see that the code successfully read all the 50 bytes lines from the file ps.txt and printed them. After reading the complete file, it was able to detect the end of file and then wrote something to it. If you refer the code, this is what we wanted our code to do.

    Now lets have a quick look at what got written to file as last line of output shown above says that something got written to file. Lets check ps.txt :

    Code:
    ...
    ...
    ...
    himanshu  1966     1  0 05:31 ?        00:00:01 /usr/bin/gnome-terminal -x /bin/sh -c '/home/himanshu/Desktop/Reliance.sh'
    himanshu  1967  1966  0 05:31 ?        00:00:00 gnome-pty-helper
    himanshu  1993     1  0 05:31 ?        00:00:00 /bin/sh /usr/lib/firefox-3.6.3/firefox
    himanshu  1998  1993  0 05:31 ?        00:00:00 /bin/sh /usr/lib/firefox-3.6.3/run-mozilla.sh /usr/lib/firefox-3.6.3/firefox-bin
    himanshu  2002  1998 20 05:31 ?        00:07:33 /usr/lib/firefox-3.6.3/firefox-bin
    himanshu  2090     1  1 05:34 ?        00:00:29 gedit /home/himanshu/Desktop/articles/go4expert/Nov2011/name_changer.txt
    himanshu  2102  1966  0 05:38 pts/1    00:00:00 bash
    himanshu  2500  1966  2 06:09 pts/0    00:00:00 bash
    himanshu  2515  2102  0 06:09 pts/1    00:00:00 ./namepid
    himanshu  2516  2515  0 06:09 pts/1    00:00:00 sh -c /bin/sh -c 'ps -aef > ps.txt'
    himanshu  2517  2516  0 06:09 pts/1    00:00:00 /bin/sh -c ps -aef > ps.txt
    himanshu  2518  2517  0 06:09 pts/1    00:00:00 ps -aef
    SomeThing to be written to file
    Just see the last line of ps.txt above, this is what we were trying to write through the code. We see that the string "SomeThing to be written to file" was successfully written to file.

    Conclusion



    To conclude, in this article, we understood the APIs like fread(), fwrite, feof() etc and learned how to use them practically in code.

    Stay tuned for more!!!
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice