× back File handling Text and binary modes Concept of buffer Opening a file Closing a file Functions used for file I/O Formatted and Unformatted I/O function System calls Create Open Close Read Write
← Previous Topic

File handling

Text and Binary modes

Concept of buffer

Opening a file

Declaration:

                    
FILE *fopen("filename.txt", "opening mode");
                    
                
  • fopen() function takes two strings as arguments, the first one is the name of the file to be open and the second one is the mode that decides which operations (read, write, append etc) are to performed on the file. On success, fopen() returns a pointer of type FILE and on error it returns NULL.
  • The return value of fopen() is assigned to a FILE pointer declared previously. For example ↓
                    
FILE *fp1, *fp2;
fp1 = fopen( "myfile.txt", "w");
fp2 = fopen("yourfile.txt", "r");
                    
                
  • After opening the file with fopen(), the name of file is not used in the program for any operation on it. Whenever we have to perform a operation on the file, we'll use the file pointer returned by fopen() function. so the name of file sometimes known as external name, while the file pointer associated with it is known as its internal name.

The second argument represents the mode in which the file is to be opened. The possible value of mode are ↓

  • "w" (write): If the file doesn't exist then this mode creates a new file for writing, and if the file already exists then the previous data is erased and the new data entered is written to the file.
  • "a" (append): If the file doesn't exist then this mode creates a new file, and if the file already exists then the new data entered is appended at the end of existing data. In this mode, the data existing in the file is not erased as in "w" mode.
  • "r" (read): This mode is used for opening an existing file for reading purpose only. The file to be opened must exist and the previous data of file is not erased.
  • "w+" (write+read): This mode is same as "w" mode but in this mode we can also read and modify the data. If the file doesn't exist then a new file is created and if the file exists then previous data is erased.
  • "r+" (read+write): This mode is same as "r" mode but in this mode we can also write and modify existing data. The file to be opened must exist and the previous data of file is not erased. Since we can add new data modify existing data so this mode is also called update mode.
  • "a+" (append+read): This mode is same as the "a" mode but in this mode we can also read the data stored in the file. If the file doesn't exist, a new file is created and if the file already exists then new data is appended at the end of existing data. We cannot modify existing data in this mode.
  • To open a file in binary mode we can append 'b' to the mode, and to open the file in text mode 't' can be appended to the mode. But since text mode is the default mode, 't' is generally omitted while opening file in text mode. For example:
    • "wb" → Binary file opened in write mode
    • "ab+" or "a+b" → Binary file opened in append mode
    • "rt+" or "r+t" → Text file opened in update mode
    • "w" → Text file open in write mode

Errors in Opening Files

  • If an error occurs in opening file, then fopen() returns NULL. So we can check for any errors in opening by checking the return value of fopen().
                    
FILE *fp;
fp = fopen("text.dat", "W");
if(fp == NULL)
{
    printf("Error in opening file");
    exit(1);
}
                    
                
  • Errors in opening a file may occur due to various reasons, for example-
    1. If we try to open a file in read or update mode, and the file doesn't exist or we do not have read permission on that file.
    2. If we try to create a file but there is no space on the disk or we don't have write permission.
    3. If we try to create file that already exists and we don't have have permission to delete that file.
    4. Operating system limits the number of files that can be opened at a time and we are trying to open more files than that number.
  • We can give full pathname to open a file. Suppose we want to open a file in DOS whose path is "E:\booksdir\names.dat, then we'll have to write as-
    fp = fopn("E:\\booksdir\\names.dat", "r");
    Here we have used double backslash because single backslash inside string is considered as an escape character, '\b' and '\n' will be regarded as escape sequences if we use single backslash. In Unix, a single forward slash can be used.
  • Never give the mode in single quotes, since it is a string not a character constant.
    fp = fopen("file.data", 'w'); /* Error */

Closing a file

Declaration ↓

                
fclose(File *fptr);
                
            

Structure of a General File Program

                
main()
{
    FILE *fp;
    fp = fopen("filename", "mode");
    ...
    ... 
    ... 
    fclose(fp);
} /* End of Main */
                
            

The functions used for file I/O are

                        
#include <stdio.h>
int main()
{
    FILE *a, *b, *c, *d;
    a = fopen("up.txt", "w");
    b = fopen("lw.txt", "w");
    c = fopen("dg.txt", "w");
    d = fopen("sp.txt", "w");
    char str[30];
    int i;
    printf("Enter a string : ");
    scanf("%s", str);
    for (i = 0; str[i] != '\0'; i++)
    {
        if (str[i] >= 'A' && str[i] <= 'Z')
            putc(str[i], a);
        else if (str[i] >= 'a' && str[i] <= 'z')
            putc(str[i], b);
        else if (str[i] >= '0' && str[i] <= '9')
            putc(str[i], c);
        else
            putc(str[i], d);
    }
    fclose(a);
    fclose(b);
    fclose(c);
    fclose(d);
    return 0;
}
                        
                    

Program that reads data from one file and writes it on another file.

                   
#include <stdio.h>

int main() {
    FILE *sourceFile = fopen("source.txt", "r");
    FILE *destinationFile = fopen("destination.txt", "w");
    
    if (sourceFile == NULL || destinationFile == NULL) {
        printf("Failed to open files.\n");
        return 1;
    }
    
    int ch;
    while ((ch = fgetc(sourceFile)) != EOF) { // The variable 'ch' is updated automatically with each call to fgetc(file) inside the while loop. 
        fputc(ch, destinationFile);
    }
    
    fclose(sourceFile);
    fclose(destinationFile);
    
    printf("Data copied successfully.\n");
    
    return 0;
}
                   
               

Formatted and Unformatted I/O function

In C programming, input/output (I/O) functions are categorized into two types: formatted and unformatted file handling functions. These functions serve different purposes and have distinct characteristics. Here's an explanation of each type:

  1. Formatted I/O functions:
    Formatted I/O functions deal with data in a human-readable format. They allow you to read data from or write data to files using a specified format. These functions provide more control over the data's representation and formatting. Some commonly used formatted I/O functions in C include:
    • printf(): Used to format and print data to the standard output (usually the console) or a file.
    • scanf(): Used to read and parse formatted data from the standard input (usually the keyboard) or a file.
    • fprintf(): Similar to printf(), but writes the formatted data to a specified file instead of the standard output.
    • fscanf(): Similar to scanf(), but reads formatted data from a specified file instead of the standard input.
    Formatted I/O functions use format specifiers (such as %d, %f, %s, etc.) to specify the data type and formatting options for input or output. These functions provide flexibility in how data is displayed or interpreted.
  2. Unformatted I/O Functions:
    Unformatted I/O functions deal with data in its raw binary format. They read or write data directly as a sequence of bytes without any specific formatting. These functions are commonly used for binary file handling, where data is read or written without any special formatting considerations. Some commonly used unformatted I/O functions in C include:
    • fread(): Reads a specified number of bytes directly from a file.
    • fwrite(): Writes a specified number of bytes directly to a file.
    • getc(), fgetc(): Reads a single character (byte) from a file.
    • putc(), fputc(): Writes a single character (byte) to a file.
    Unformatted I/O functions are useful when working with binary data, such as image files, sound files, or structured data stored in binary format. They provide a straightforward way to read and write raw data without any specific formatting requirements.
It's important to choose the appropriate type of I/O functions based on your requirements and the nature of the data you are dealing with. Formatted I/O functions provide more control over formatting and are suitable for human-readable data, while unformatted I/O functions work with raw binary data.

System calls

Important terminology

File descriptor

  • The file descriptor is an integer that uniquely itentifies an open file of the process.
  • In operating systems, a file descriptor is an abstract representation of an opened file or I/O stream. It is a non-negative integer that uniquely identifies an open file within a process. File descriptors are used to perform various operations on files, such as reading, writing, and closing.
  • When you open a file using 'open()' system call library function, a file descriptor is returned. You can think of it as a handle or reference to the opened file. This file descriptor is then used in subsequent system or library calls to perform operations on the file.

Create

Syntax of create()

                
int create (char *filename, mode_t mode);
                
            

Parameter

Return value

How create() works in OS

Open

Parameters

Example of open

                   
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fileDescriptor = open("example.txt", O_RDONLY);
    if (fileDescriptor == -1) {
        // Handle error if file couldn't be opened
    }

    // Perform operations on the opened file

    close(fileDescriptor); // Close the file descriptor

    return 0;
}
                   
               

Close

Parameter

Return value

Example ↓

                   
#include <unistd.h>

int main() {
    int fileDescriptor = open("example.txt", O_RDONLY);
    if (fileDescriptor == -1) {
        // Handle error if file couldn't be opened
    }

    // Perform operations on the opened file

    close(fileDescriptor); // Close the file descriptor

    return 0;
}

                   
               

Read

Parameters

Return value

Important points

Example ↓

                   
#include <fcntl.h>
#include <unistd.h>

#define BUFFER_SIZE 1024

int main() {
    int fileDescriptor = open("example.txt", O_RDONLY);
    if (fileDescriptor == -1) {
        // Handle error if file couldn't be opened
    }

    char buffer[BUFFER_SIZE];
    ssize_t bytesRead = read(fileDescriptor, buffer, BUFFER_SIZE);
    if (bytesRead == -1) {
        // Handle error if reading failed
    }

    // Process the read data

    close(fileDescriptor); // Close the file descriptor

    return 0;
}

                   
               

Write

Parameters

Return value

Example ↓

                   
#include <fcntl.h>
#include <unistd.h>

int main() {
    int fileDescriptor = open("example.txt", O_WRONLY | O_CREAT, 0644);
    if (fileDescriptor == -1) {
        // Handle error if file couldn't be opened
    }

    char data[] = "Hello, world!";
    ssize_t bytesWritten = write(fileDescriptor, data, sizeof(data) - 1);
    if (bytesWritten == -1) {
        // Handle error if writing failed
    }

    close(fileDescriptor); // Close the file descriptor

    return 0;
}

                   
               

0644: File permission mode (used with open()), specifies read and write permissions for the owner and read-only permissions for others.

Reference ↓