What is Binary File I/O in C?

Question: What is Binary I/O in C Programming?

Answer: By now, we are familiar with File I/O on text streams. We have seen that when we perform I/O with numeric values, for ex. integers, floats etc., value is firstly converted according to format code in the format string before reading from or writing to the file. This conversion is extra overhead which is accompanied with loss of precision too. Let’s take a simple C program to understand this, I write below just the relevent code

    in_out = fopen("test.txt", "a+");
 
    float val = 10.0/3.0, dval;

now write value of ‘val’ to file,

    fprintf(in_out, "%f", val);

Let’s read value from the file “test.txt” back to float type variable, say dval,

advertisement
advertisement
    fscanf(in_out, "%f", &dval);

and test for equality

    val == dval;

What do you think; how will it turn to? Truely, this relationship doesn’t hold. Why? Try to unravell it yourself. It’s Interesting!

Sanfoundry Certification Contest of the Month is Live. 100+ Subjects. Participate Now!

Bacause of overhead of conversion and loss of precision while writing to or reading from on text streams, writing to and/or reading from data in binary is most efficient way. This doesn’t involve any overhead of conversion and loss of precision. But binary data isn’t readable to humans therefore this technique is useful only for data that is subsequentally to be given to a program. Let’s take a simple C program to understand binary input and output

/* binary_io.c -- */
/* size_t fread(void *buffer, size_t size, size_t count, FILE * stream) */
/* size_t fwrite(void *buffer, size_t size, size_t count, FILE * stream) */
 
#include <stdio.h>
#include <stdlib.h>
#define TEXTSIZE 20
#define SIZE 10
 
int main(void)
{
    int i, n_values;
    long current, changed, bcurrent, bchanged;
    float fval;
    FILE *text_in_out, *binary_in_out;
    char tf_name[TEXTSIZE], bf_name[TEXTSIZE];
 
    float fvalues[SIZE] = {2.0, 10.9/5.4, 23.45, 1.23/7, 0.34,
                      5.67, 10.87, 2.3, 12.0, 6.67};
 
    float dvalues[SIZE]; /* buffer for duplicate floats */
 
    printf("user, give name for text file:");
    scanf("%s", tf_name);
 
    printf("\n");
 
    /* open text file in update mode */
    text_in_out = fopen(tf_name, "a+");
    if (text_in_out == NULL) {
        perror("File Open");
        exit(EXIT_FAILURE);
    }
 
    /* write floats to text file named tf_name */
    for (i = 0; i < SIZE; i++)
        fprintf(text_in_out, "%f\n", fvalues[i]);
 
    /* let's check current position in text file */
    current = ftell(text_in_out);
    printf("Next read or write will occur at offset:%ld from the "
           "beginning.\n", current);
 
    /* call fseek() to set to read from beginning */
    fseek(text_in_out, -current, SEEK_END);
 
    /* changed position in text file */
    changed = ftell(text_in_out);
    printf("Next read or write will occur at offset:%ld from the "
           "beginning.\n", changed);
 
    /* before attempt to read from the file, flush text_in_out stream */
    fflush(text_in_out);
 
    /* perform reading from the file */
    /* attempt to read floating values from the file back to program */
    printf("\nfloat values:\n");
    for (i = 0; i < SIZE; i++) {
        fscanf(text_in_out, "%f", &fval);
        printf("%f\n", fval);
    }
 
    /* let's write float values efficiently in binary */
    printf("\nLet's write float values in binary...\n");
    printf("user, give name for binary file:");
    scanf("%s", bf_name);
 
    printf("\n");
 
    /* open binary file in update mode */
    binary_in_out = fopen(bf_name, "ab+");
    if (binary_in_out == NULL) {
        perror("File Open");
        exit(EXIT_FAILURE);
    }
 
    /* write float values to binary file using fwrite() */
    /*
     * int fwrite(void *buffer, size_t size_of_element,
                    size_t no_of_elements, FILE *stream);
     */
    n_values = fwrite(fvalues, sizeof(float), SIZE, binary_in_out);
    printf("No of values written to binary file \"%s\" is %d.\n",
            bf_name, n_values);
 
    /* flushing stream binary_in_out */
    fflush(binary_in_out);
 
    /* let's check current position in binary file */
    bcurrent = ftell(binary_in_out);
    printf("Binary File: Next read or write will occur at offset:%ld "
           "from the beginning.\n", bcurrent);
 
    /* let's set to read from beginning in binary file using fseek() */
    fseek(binary_in_out, -bcurrent, SEEK_END);
 
    bchanged = ftell(binary_in_out);
    printf("Binary File: Next read or write will occur at offset:%ld "
           "from the beginning.\n", bchanged);
 
    /* let's read floats from binary file back to buffer in program */
    /*
     * int fread(void *buffer, size_t size_of_element,
                 size_t no_of_element, FILE *stream);
     */
    n_values = fread(dvalues, sizeof(float), n_values, binary_in_out);
    printf("No of values read into buffer \'dvalues\' from binary file "
            "\"%s\" is %d.\n", bf_name, n_values);
 
    /* let's compare fvalues and dvalues */
    printf("\nLet's compare float values in buffers: fvalues and "
           "dvalues:\n");
    for (i = 0; i < SIZE; i++) {
        if (fvalues[i] == dvalues[i])
            printf("fvalues[%d] and dvalues[%d] is SAME.\n", i, i);
    }
 
    return 0;
}

Let’s turn to output below

advertisement
user, give name for text file:tfile
 
Next read or write will occur at offset:93 from the beginning.
Next read or write will occur at offset:0 from the beginning.
 
float values:
2.000000
2.018518
23.450001
0.175714
0.340000
5.670000
10.870000
2.300000
12.000000
6.670000
 
Let us write float values in binary...
user, give name for binary file:bfile
 
No of values written to binary file "bfile" is 10.
Binary File: Next read or write will occur at offset:40 from the beginning.
Binary File: Next read or write will occur at offset:0 from the beginning.
No of values read into buffer 'dvalues' from binary file "bfile" is 10.
 
Let's compare float values in buffers: fvalues and dvalues:
fvalues[0] and dvalues[0] is SAME.
fvalues[1] and dvalues[1] is SAME.
fvalues[2] and dvalues[2] is SAME.
fvalues[3] and dvalues[3] is SAME.
fvalues[4] and dvalues[4] is SAME.
fvalues[5] and dvalues[5] is SAME.
fvalues[6] and dvalues[6] is SAME.
fvalues[7] and dvalues[7] is SAME.
fvalues[8] and dvalues[8] is SAME.
fvalues[9] and dvalues[9] is SAME.

The concept of the program is very simple. It writes 10 floats, given as fvalues[SIZE], to file “tfile” which has been shown up to the user on the stdout. Then the same floats written to a binary file “bfile”, then read back into buffer float array as ‘dvalues[SIZE]’ in program and compared to see if all corresponding pairs matched while printing them one by one on stdout.

Observe that there’s no overhead of conversion and no loss of precision when writing numeric values to binary file.

Sanfoundry Global Education & Learning Series – 1000 C Tutorials.

advertisement
If you wish to look at all C Tutorials, go to C Tutorials.

advertisement
advertisement
Subscribe to our Newsletters (Subject-wise). Participate in the Sanfoundry Certification contest to get free Certificate of Merit. Join our social networks below and stay updated with latest contests, videos, internships and jobs!

Youtube | Telegram | LinkedIn | Instagram | Facebook | Twitter | Pinterest
Manish Bhojasia - Founder & CTO at Sanfoundry
Manish Bhojasia, a technology veteran with 20+ years @ Cisco & Wipro, is Founder and CTO at Sanfoundry. He lives in Bangalore, and focuses on development of Linux Kernel, SAN Technologies, Advanced C, Data Structures & Alogrithms. Stay connected with him at LinkedIn.

Subscribe to his free Masterclasses at Youtube & discussions at Telegram SanfoundryClasses.