Sunday, October 4, 2015

C language : File Input and output



Here we will see some methods of file input and output. That will help in writing some good code, where we want to process file data.

Everything is type of FILE when we see OS. The stdin,stdout,stderr  all are treated as file.

We will start with the simple C code of our own copy tool.

The functions which we will see are

int putchar(int)  : Its output on stdout file , whatever int we put in it. Also it returns the same int and on error EOF.

int getchar(void) : Its reads from the standard input (stdin) and returns what is the character in integer format.

Now on gcc , if we have to read input from a file, we can use getchar function in case of scanf() and using < we can tell getchar to read data from the input file rather than stdin.

> ./program  < input.txt

Similarly if we have used putchar in our program and want to save data in some file rather then getting displayed on console, we can do

>./program > output.txt

int getc(FILE *) :  This is similar to getchar, only diff it has parameter FILE pointer, in which we can specify our file name.

int putc(int,FILE *) :  same as putchar, only we can specify the file where we want to put data.

Two more function related to File.

1)  File * fopen(filename,mode) : Mode can be "w","r","a".
2) fclose(File *)


One more thing,

till now we were using
int main(),   But what if we want to pass some arguments to main from command line, Then we will use

int main( int argc, char *argv[])

argc is count of how manu arguments were given, every argument which is given is treated as STRING.

so

>./program 1 2 3

will be treated as  4 arguments    ./argument is first  and 1,2,3 next three. We have to take care inside program whether we want to convert them to int or any other type.


Now the file copy program :

#include<stdio.h>

int main(int argc ,char *argv[])
{
   int c;
   FILE *fp1;
   FILE *fp2;
 

   fp1 = fopen(argv[1],"r");
   fp2 = fopen(argv[2],"w");
   while( (c =getc(fp1))!=EOF)
   {
     putc(c,fp2);
   }
     fclose(fp1);fclose(fp2);
}

if we create output file with name copy

> gcc -o copy  program.c

> ./copy program.c dup_copy.c  // will copy program.c  to dup_copy.c


Now we will see the STDERR file, like STDOUT it also prints output onto console. I myself was not able to find good reason for doing this.

Since first of all I am not getting any way where I can use stderr to give additional  compile errors or runtime errors .

Most of the times it works like simple printf or sprintf.

On searching I found a very good blog, which told history and usage of stderrr.

http://www.jstorimer.com/blogs/workingwithcode/7766119-when-to-use-stderr-instead-of-stdout


In case you are not interested in reading it, the brief gist is

> When we are writing programs which doesn't simply involves console output, but some other way there we can clearly see difference between STDERR and STDOUT. Since in those cases we need to analysis errors and output. And if all the output is at same place it will be difficult to separate the two.

So we will not going to go deep in STDERR, untill we get a good case to use it.

Two more ways to output and input data using file.

fprintf and fscanf  , they work same as printf and scanf.

only thing which differs is first parameter of both is FILE pointer.


So now we have seen how to read character by character and also output it to any file.

But sometimes it can be very slow, So there are two more functions provided in C, which reads line by line and also for output we have a function.

char *fgets ( char *, int , FILE *)   and int fputs(char *,File *)

No need to explain FILE pointer,

Char * pointer holds the character array, IN case of  fgets the second parameter specifies the max number of character to be read.

Also the return value of fgets is same as its first parameter. It differs when end of line is encountered.

fputs returns EOF on error , else Zero.

To understand the  return value difference ...lets make a program.

We will test it using below scenarios.

1) When in fgets we have given  numberofcharacters less than in one line.
2) When in fgets we have given numberofcharacters more than in one line.
3) fgets and fputs  return value when FILE don't exist.
4) fgets and fputs  return value when FILE is empty.

Okay , so here is learning from the program about fgets.


#include<stdio.h>

int main()
{

FILE *fp;
char *c;
char c_dup[10]={};

fp = fopen("read.txt","r");

printf("fp value %d\n ",fp);
c = fgets(c_dup,10,fp);

printf("%p \n",c);
printf("%p \n",c_dup);

printf("%s \n",c);
printf("%s \n",c_dup);
return 0;
}



1) If file doesn't exist or can't be read. Then fp will return NULL. AND we should check this value, else we will get runtime error, segmentation fault.

2) The  return value and first parameter of fgets points to same address, if some text is returned and this address is of the CHAR * pointer we passed to fgets.

3) If file is empty, then fgets will return NULL/EOF , whereas char * will be empty string. 

4) If number of characters is more than present in the line, then characters present till the end of line will be returned.

In case of fputs, even if FILE can't be open or doesn't exist, it will return -1 , if write is successful, then 1 is return

In case we want the input file to be STDIN  and output file to be STDOUT,   you can use 

int puts (char *)   and  char *gets(char *)

No need of number of character is needed for gets.




No comments:

Post a Comment