Login

Username:

Password: 

Join us Now |  Forgot Password? | Forgot UserName?

C

Learn step by step



C-File I/O (Using Text-Files)

The file I/O functions in the C language are straightforward and easy to understand. For make use of these functions we have to include the stdio library.

The file I/O functions stdio library contains are:

  • fopen- It opens a text file.
  • fclose-It closes a text file.
  • feof-It detects end-of-file marker in a file.
  • fscanf-It reads formatted input from a file.
  • fprintf-It prints formatted output to a file.
  • fgets-It reads a string from a file.
  • fputs-It prints a string to a file.
  • fgetc-It reads a character from a file.
  • fputc-It prints a character to a file.
File I/O: opening a text file

The fopen function is used to open a text file. we also have to use a specified mode when we open a file. The three most common modes are read (r), write (w), and append (a)


#include<stdio.h>
int main()
{
FILE *ptr_file;
int x;
ptr_file =fopen("output.txt", "w");
if (!ptr_file)
return 1;
for (x=1; x<=10; x++)
fprintf(ptr_file,"%d\n", x);
fclose(ptr_file);
return 0;
}

So let us take a look at the example:

ptr_file =fopen("output", "w");

The fopen statement opens a file "output.txt" in the write mode. If the file does not exist it will be created. But we must be careful! If the file exists, it will be destroyed and fully new file is created. The fopen command returns a pointer to the file specified, which is stored in the variable ptr_file. If the file cannot be opened (for any reason) the variable ptr_file will contain NULL.

if (!ptr_file)

Given if statement after de fopen, will check that fopen was successful or not. If fopen was not successful, the code will return a one. (Indicating that something gone wrong).

for (x=1; x<=10; x++)

This for loop count to ten, starting from one.

fprintf(ptr_file,"%d\n", x);

The fprintf statement should look very familiar to you. It can be almost used in the same manner as printf. The only difference is that it uses the file pointer as its first parameter.

fclose(ptr_file);

The fclose statement will close the opened file. This command must be given, especially when we are writing into files. So don't forget to write it. we have to be careful that we don't type "close" instead of "fclose", because the close function exists. But it does not close the files properly. (If there are a lot of files open but not closed properly, program will eventually run out of file handles and/or memory space and crash.)

File I/O: reading a text file

If we want to read a file we have to open it for reading in the read ('r') mode. Then the fgets library function can be used to read the contents of the file. (It's also possible to make use of the function fscanf. But for using fscanf we have to be sure that the file is perfectly formatted or fscanf will not handle it properly).


#include<stdio.h>
int main()
{
FILE *ptr_file;
char buf[1000];
ptr_file =fopen("input.txt","r");
if (!ptr_file)
return 1;
while (fgets(buf,1000, ptr_file)!=NULL)
printf("%s",buf);
fclose(ptr_file);
return 0;
}

Note that the printf statement does not have the new-line (\n) in the format string. This is not necessary because the function fgets adds the \n to the end of each line it reads.

File "input.txt" is opened for reading using function fopen in the read mode (r). The function fgets will read each line(with a maximum of 1000 characters per line.) If the end-of-file (EOF) is reached the fgets function will return a NULL value. Each line will be printed on stdout (normally your screen) until the EOF is reached. File is then closed and the program will end.

C-File I/O (Using Binary-Files)

In an earlier tutorial we talked about file I/O functions and the use of text files. In this C tutorial we are going to talk about the use of binary files.

Binary files

Binary files are similar to arrays of structures, except structures are in a disk-file rather than an array in memory. They have two features that distinguish them from text files:

  • We can instantly use any structure in the file.
  • We can change the contents of a structure anywhere in the file.

After we have opened the binary file, we can read and write a structure or seek a specific position in the file. File position indicator points to record 0 when the file is opened.

Read operation reads the structure where the file position indicator is pointing to. After reading the current structure the pointer is moved to point at the next structure.

Write operation will write to the currently pointed-to structure. After that the file position indicator is moved to point at the next structure.

The function fseek will move the file position indicator to the record that is requested.

Remember that we keep track of things, because the file position indicator can not only point at the beginning of a structure, but it can also point to any byte in the file.

The fread and fwrite functions take four parameters:

  • A memory address
  • Number of bytes to read per block
  • Number of blocks to read
  • A file variable
fread(&my_record,sizeof(struct rec),2,ptr_myfile);

Given fread statement says to read x bytes (size of rec) from the file ptr_myfile into memory address &my_record. Only 2 blocks are requested. Changing the value of number of blocks to read from 2 into 10 will read in 10 blocks of x bytes at once.


#include<stdio.h>
/* Our structure */
struct rec
{
int x,y,z;
};
int main()
{
int counter;
FILE *ptr_myfile;
struct rec my_record;
ptr_myfile=fopen("test.bin","wb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
for ( counter=1; counter <= 10; counter++)
{
my_record.x= counter;
fwrite(&my_record, sizeof(struct rec), 1, ptr_myfile);
}
fclose(ptr_myfile);
return 0;
}

In the example we declare a structure rec with the members x,y and z of integer type. In the main function we open (fopen) a file for writing (w). Then we check if the file is open, if not, then an error message is displayed and we exit from the program. In the for loop we fill the structure member x with a number. Then after we write the record to the file. We will do this ten times, thus creating ten records. After writing ten records, we will close the file.

Now we have written to a file, let's read from the file we have just created. Take a look at the given example:


#include<stdio.h>
/* Our structure */
struct rec
{
int x,y,z;
};
int main()
{
int counter;
FILE *ptr_myfile;
struct rec my_record;
ptr_myfile=fopen("test.bin","rb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
for ( counter=1; counter <= 10; counter++)
{
fread(&my_record,sizeof(struct rec),1,ptr_myfile);
printf("%d\n",my_record.x);
}
fclose(ptr_myfile);
return 0;
}

The only two lines that are changed are in the "for loop". With the fread we read-in the records (1 by 1). After we have read the record we print the member x.

The only thing we need to explain is function fseek. The fseek function must be declared like this:

int fseek(FILE * stream, long int offset, int whence);

The fseek function sets the file position indicator for the stream pointed to. The new position, measured in characters from the beginning of the file, and is obtained by adding offset to the position specified by whence. There are three macros which are declared in stdio.h called: SEEK_SET, SEEK_END and SEEK_CUR.

The SEEK_END can be used if you want to go to the EOF(end of file). (Using negative numbers it's possible to move from the end of the file.)

If the declared position by whence is SEEK_SET, then the position is the beginning of the file.

If the declared position by whence is SEEK_CUR then the position is set, x bytes, from the current position.


#include<stdio.h>
/* Our structure */
struct rec
{
int x,y,z;
};
int main()
{
int counter;
FILE *ptr_myfile;
struct rec my_record;
ptr_myfile=fopen("test.bin","rb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
for ( counter=9; counter >= 0; counter--)
{
fseek(ptr_myfile,sizeof(struct rec)*counter,SEEK_SET);
fread(&my_record,sizeof(struct rec),1,ptr_myfile);
printf("%d\n",my_record.x);
}
fclose(ptr_myfile);
return 0;
}

In example we are using fseek to seek the last record in file. This record we read with fread statement and with the printf statement we print member x of the structure my_record. As we can see the for loop also changed. The for loop will now countdown to zero(0). This counter is then used in the fseek statement to set the file pointer at the desired record. Result is that we read-in the records in the reverse order.

Note: If we set the file position indicator to a position in a file and we want the first position in a file then we can use the function rewind to the first position in the file. Function rewind can be used like:


#include<stdio.h>
/* Our structure */
struct rec
{
int x,y,z;
};
int main()
{
int counter;
FILE *ptr_myfile;
struct rec my_record;

ptr_myfile=fopen("test.bin","rb");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
fseek(ptr_myfile, sizeof(struct rec), SEEK_END);
rewind(ptr_myfile);
for ( counter=1; counter <= 10; counter++)
{
fread(&my_record,sizeof(struct rec),1,ptr_myfile);
printf("%d\n",my_record.x);
}
fclose(ptr_myfile);
return 0;
}

With the fseek statement in the example we go to the EOF. And then we rewind to first position in the file. Then read-in all the records and print the value of member x. Without the rewind we will get garbage.



Related Videos