Unit 5 C
Unit 5 C
Files
A file represents a sequence of bytes, regardless of it being a text file or a binary file. C
programming language provides access on high level functions as well as low level (OS
level) calls to handle file on your storage devices. This chapter will take you through the
important calls for file management.
1. Creation of a new file (fopen with attributes as “a” or “a+” or “w” or “w++”)
2. Opening an existing file (fopen)
3. Reading from file (fscanf or fgets)
4. Writing to a file (fprintf or fputs)
5. Moving to a specific location in a file (fseek, rewind)
6. Closing a file (fclose)
The text in the brackets denotes the functions used for performing those operations.
FILE *filePointer;
The second parameter can be changed to contain all the attributes listed in the above table.
FILE * filePointer;
Writing a file –:
The file write operations can be perfomed by the functions fprintf and fputs with
similarities to read operations. The snippet for writing to a file is as :
FILE *filePointer ;
Closing a file –:
After every successful fie operations, you must always close a file. For closing a file,
you have to use fclose function. The snippet for closing a file is given as :
FILE *filePointer ;
fclose(filePointer)
SEQUENTIAL ACCESS
Sequential access is a term describing a group of elements (such as data in a memory array
or a disk file or on magnetic tape data storage) being accessed in a predetermined, ordered
sequence. ... Sequential access is sometimes the only way of accessing the data, for example
if it is on a tape.
A common example of sequential access is with a tape drive, where the device must move
the tape's ribbon forward or backward to reach the desired information. The opposite would
be RAM (Random Access Memory) going anywhere on the chip to access the information.
The biggest drawback of sequential access is that it's very slow. You will see sequential
access mostly in backup tapes, or the big, clunky magnetic tapes that are used to backup large
amounts of data. For this purpose, the method is acceptable because the speed of access isn't
important.
Random access
Random access (more precisely and more generally called direct access) is the ability
to access an arbitrary element of a sequence in equal time or any datum from a population of
addressable elements roughly as easily and efficiently as any other, no matter how many
elements may be in the set.
Random access is the capability to have access to any item from a given population of
elements at random. Random access is the opposite of sequential access, as sequential access
locates elements by beginning at a particular predefined location and then traversing through
all of the information in order to find the given item. Random access has gained interest due
to the fact that one can retrieve a record irrespective of the position in which it is located.
Disks hold data in files. Files can hold either programs or data. Your programs must be
loaded from disk into memory before you can run them. You also must load data from the
disk file into variables before you can work with the data. The variables also hold data before
the data goes to a disk file.
Two types of files exist: sequential-access files and random-access files. Their types
determine how you can access them. If you work with a sequential-access file, you have to
read or write the file in the order of the data. In a random-access file, you can jump around,
reading and writing any place in the file.
All disk files have names that conform to the same naming rules as filenames on your
operating system. Before you can use a disk file, whether to create, read, or change the data
in the file, you must open the file.
You can’t use a disk file without opening the file. Instead of pulling out a drawer, your
computer attaches something called a file pointer to the file and makes sure that the disk is
properly set up to hold the file you specify.
Opening a File
To open a file, you must use the fopen() function, whose description is included stdio.h.
Before seeing fopen(), you have to understand the concept of a file pointer.
A regular pointer holds the address of data in a variable. A file pointer holds the disk location
of the disk file you’re working with.
As with any variable, you can name file pointers anything you want.
Note : This makes the file pointer global, which is a fancy term meaning that the entire
program can use the file. (Most other kinds of variables are local, not global.) FILE is defined
in stdio.h.
After you define a file pointer, you can connect that pointer to a file with fopen(). After you
specify fopen(), you can use the file throughout the rest of the program.
#include <stdio.h>
main()
For the rest of the program, you’ll access the cdata.txt file via the file pointer, not via the
filename.
Warning : Close all open files when you’re finished with them, or you could lose some data.
fclose() is the opposite of fopen(). In its parentheses, fclose() requires a file pointer of the file
you want to close.
If the file pointer equals 0, you know that an error happened. For example, if you attempt to
open a file on a disk drive that doesn’t exist, fopen() returns an error.
The “w” (the second argument in the previous code’s fopen()) means write.
You’ll do only three things with a sequential file: create it, read it, and add to it (write to it).
To write to a file, you can use fprintf(). fprintf() is easy because it’s just a printf() with a file
pointer at the beginning of its parentheses. The following program creates a file and writes
some data to it using fprintf():
Warning : Opening a file in “w” mode overwrites an existing file with the same name. So if
you run the previous program twice, the file will have only your data from the second run. If
you want to build on to the file and keep the previous data, you need to open the file in “a”
mode.
Use fgets() to read the contents of the file. fgets() is nothing more than a gets() that you can
direct to a disk file. fgets() reads lines from a file into character arrays (or allocated heap
memory pointed to with a character pointer).
Tip : Think of the f at the beginning of fputs() and fgets() as standing for file. puts() and
gets() go to the screen and keyboard, respectively; fputs() and fgets() write and read their data
from files.
Unlike gets(), fgets() requires that you specify a maximum length for the array you’re reading
into. You might read past the end of the file (producing an error) if you’re not careful, so be
sure to check for the location of the end of the file.
fgets() reads one line at a time. If you specify more characters to read in the fgets() than
actually reside on the file’s line you’re reading, fgets() stops reading the line of data as long
as the file’s lines end with a newline character. The previous program that created
the bookinfo.txt file always wrote \n at the end of each line so that subsequent fgets()
functions could read the file line by line.
The following program loops through a file and prints the info on the screen.
#include <stdio.h>
#include <stdlib.h>
FILE * fptr;
main()
fptr = fopen("/tmp/BookInfo.txt","rtr != 0)
{
while (!feof(fptr))
if (!feof(fptr))
puts(fileLine);
else
return(0);
}
Random accessing file
The ftell function
The ftell() function tells us about the current position in the file (in bytes).
Syntax:
pos = ftell(fptr);
Where, fptr is a file pointer. pos holds the current position i.e., total bytes read (or written).
Example:
If a file has 10 bytes of data and if the ftell() function returns 4 then, it means that 4 bytes has
already been read (or written).
We use the rewind() function to return back to the starting point in the file.
Syntax:
rewind(fptr);
We use the fseek() function to move the file position to a desired location.
Syntax:
Where, fptr is the file pointer. offset which is of type long, specifies the number of positions
(in bytes) to move in the file from the location specified by the position.
Following are the list of operations we can perform using the fseek() function.
Operation Description
fseek(fptr, 0, 0) This will take us to the beginning of the file.
fseek(fptr, N, 1) This will take us N bytes forward from the current position in the file.
fseek(fptr, -N, 1) This will take us N bytes backward from the current position in the file.
fseek(fptr, -N, 2) This will take us N bytes backward from the end position in the file.
Write a program in C to save alphabet A to Z in file and then print the letters using fseek
function
#include <stdio.h>
int main(void) {
// integer variable
int i;
// character variable
char ch;
// file pointer
FILE *fptr;
if (fptr != NULL) {
printf("File created successfully!\n");
}
else {
printf("Failed to create the file.\n");
// exit status for OS that an error occured
return -1;
}
// close connection
fclose(fptr);
// reference
printf("\nReference:\n");
for (i = 0; i < 26; i++) {
printf("%d ", (i+1));
}
printf("\n");
for (i = 65; i <= 90; i++) {
// print character
printf("%c", (i));
// manage space
if (i - 65 >= 9) {
printf(" ");
}
else {
printf(" ");
}
}
printf("\n\n");
// rewind
printf("rewind\n");
rewind(fptr);
// close connection
fclose(fptr);
return 0;
}
Output:
File created successfully!
Reference:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
ABCDEFGHIJ K L M N O P Q R S T U V W X Y Z
Curr pos: 0
1st char: A
Curr pos: 1
5th char: E
Curr pos: 5
26th char: Z
Curr pos: 26
rewind
Curr pos: 0
10th char: J
Curr pos: 10
15th char: O
Curr pos: 15
20th char: T
Curr pos: 20
01 #include <stdio.h>
02 #include <math.h>
03
04 int main(int argc, char* argv[]){
05 int i,sum,digit, n,avg;
06 FILE *fin;
07 sum = 0;
08
09 fin = fopen("testdata29", "r");
10 for(i = 0; (i<=sum); i++){
11 fscanf(fin, "%d", &n);
12 digit += n;
13 n++;
14 avg = avg +(digit/ sum);
15 printf("The average is %d.\n", avg);
16 }
17 fclose(fin);
18 return 0;
19 }
The command line arguments are handled using main() function arguments
where argc refers to the number of arguments passed, and argv[] is a pointer array which
points to each argument passed to the program. Following is a simple example which checks
if there is any argument supplied from the command line and take action accordingly −
#include <stdio.h>
if( argc == 2 ) {
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
}
When the above code is compiled and executed with single argument, it produces the
following result.
$./a.out testing
The argument supplied is testing
When the above code is compiled and executed with a two arguments, it produces the
following result.
When the above code is compiled and executed without passing any argument, it produces
the following result.
$./a.out
One argument expected
It should be noted that argv[0] holds the name of the program itself and argv[1] is a pointer
to the first command line argument supplied, and *argv[n] is the last argument. If no
arguments are supplied, argc will be one, and if you pass one argument then argc is set at 2.
You pass all the command line arguments separated by a space, but if argument itself has a
space then you can pass such arguments by putting them inside double quotes "" or single
quotes ''. Let us re-write above example once again where we will print program name and
we also pass a command line argument by putting inside double quotes −
#include <stdio.h>
if( argc == 2 ) {
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
else {
printf("One argument expected.\n");
}
}
When the above code is compiled and executed with a single argument separated by space
but inside double quotes, it produces the following result.