Last Updated:

Handling Binary Files in C++

 

When information is written to a binary file, characters and numbers are written as a sequence of bytes.

In order to write data to a binary file, you need to:

  1. describe a file variable of type FAIL * using the FILE *filename statement, where filename is the name of the variable where the pointer to the file will be stored.
  2. open a file with fopen
  3. write information to a file using the fwrite function
  4. close the file using the fclose function

In order to read data from a binary file, you need to:

  1. describe a variable of type FILE *
  2. open a file with fopen
  3. read the necessary information from the file using the fread function, while monitoring whether the end of the file is reached.
  4. close the file using the fclose function

Let's look at the basic functions required to work with binaries.

To open a file, the fopen function is intended.

FILE *fopen(const *filename, const char *mode)

Here, filename is a string that stores the full name of the file to be opened, mode is a string that specifies the mode of work with the file; the possible values are as follows:

  • «rb" — open the binary file in read mode;
  • «wb" — create a binary file to write to; if it exists, its contents are cleaned;
  • «ab" — create or open a binary file to add to the end of the file;
  • «rb+" — open an existing binary file in read/write mode;
  • «wb+" — open the binary file in read/write mode, the existing file is cleared;
  • «ab+" — the binary file is opened or created to correct existing information and add new information to the end of the file.

The function returns null in the file variable f if the file is not opened successfully. After the file is opened, its 0th byte is available, the file pointer is 0, the value of which is shifted by the read (written) number of bytes as it is read or written. The current value of the file pointer is the byte number from which the read or write operation will occur.

To close the file, the fclose function is intended:

int fclose(FILE *filename);

It returns 0 if the file closes successfully and the EOF fails.

The remove function is designed to delete files:

int remove(const char *filename);

This feature removes a file named filenema from the disk. The file that you want to delete must be closed. The function returns a non-zero value if the file could not be deleted.

To rename files, the rename function is intended:

int rename(const char *oldfilename, const char *newfilename);

The first parameter is the old file name, the second is the new one. Returns 0 if the program completes successfully.

Reading from a binary file is done using the fread function:

fread(void *ptr, size, n, FILE *filename);

The fread function reads n size elements from the filename file to the ptr array. The function returns the number of items read. After reading from a file, its pointer is shifted by n*size bytes.

Writing to the binary file is done using the fwrite function:

fwrite(const void *ptr, size, n, FILE *filename);

The fwrite function writes size elements to the filename file from the ptr array n. The function returns the number of items recorded. After writing the information to the file, the pointer is shifted by n*size bytes.

To control the achievement of the end of the file there is a feof function:

int feof(FILE *filename);

It returns a non-zero value if the end of the file is reached.

For a more accurate assimilation of the material, I propose to consider a couple of standard tasks.

Task 1

Create a binary file D:\\game\\noobs.dat and write the integer n and n real numbers to it.

Decision:

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
27
28
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
setlocale (LC_ALL, «RUS»);
int n, i;
double a;
FILE *f; describe the file variable
, create a binary file in the write
mode f=fopen("D:\\game\\noobs.dat""wb");;
enter the number n
cout<< "n="; cin>>n;
fwrite(&n, sizeof(int)1, f);
loop for entering n real numbers
for (i=0; i<n; i++)
{
entering the next real number
cout<< "a=";
cin>>a;
writing a large number to the binary file
fwrite(&a, sizeof(double)1, f);
}
close
the file fclose(f);
system(«pause»);
return 0
;
}

 

D:\\game\\noobs.dat

Решение:

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
27
28
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
setlocale (LC_ALL, «RUS»);
int n, i;
double *a;
FILE *f; describe the file variable
open an existing binary file in read
mode f=fopen("D:\\game\\noobs.dat""rb");;
read one integer from the file into the variable n
fread(&n, sizeof(int),1, f);
output n to the screen
cout<<"n="<<n<<endl;
memory allocation for an array of n numbers
a=new double[n];
reading n real numbers from a file into an array a
fread(a, sizeof(double),n, f);
Displaying the array on
the screen for (i=0; i<n; i++)
cout<<a[i]<<"\t";
cout<<endl;
close
the file fclose(f);
system(«pause»);
return 0
;
}

A binary file is a sequential data structure, and once you open a file, the first byte stored in the file is available. You can sequentially write or read data from a file. Let's say you have to count the fifteenth number and then the first. With sequential access, you can do this in the following way:

1
2
3
4
5
6
7
8
9
10
int n, i;
double a;
FILE *f;
f=fopen(«D:\\game\\noobs.dat»«rb»);
for (i=0; i<15; i++)
fread(&a, sizeof(double)1, f);
fclose(f);
f=fopen(«D:\\game\\noobs.dat»«rb»);
fread(&a, sizeof(double)1, f);
fclose(f
);

As you can see, reading numbers from a file and then reopening the file is not the most convenient way. It is much more convenient to use the fseek function to move the file pointer to a given byte.

int fseek(FILE *filename, long int offset, int origin);

The function sets the pointer to the current position of the F file according to the origin origin origin and offset offset value. The offset parameter is equal to the number of bytes by which the file pointer will be offset relative to the origin parameter. The value for the origin parameter should be one of the following offset offset reference values defined in the stdio.h header:

  • SEEK_SET from the beginning of the file.
  • SEEK_CUR from the current position;
  • SEEK_END is at the end of the file.

the function returns a zero value if the operation is successful and a non-zero value if an offset fails

The fseek function actually implements direct access to any value in the file. You only need to know the location (byte number) of the value in the file. Let's look at the use of direct access in binary files on the example of solving the following problem.

Task 3

In the D:\\game\\noobs binary file created earlier.dat, swap the largest and smallest of the real numbers.

The algorithm for solving the problem consists of the following stages:

  1. read the real thing from the file to array a.
  2. search the array a for the maximum (max) and minimum (min) values and their numbers (imaximin).
  3. Move the file pointer to the maximum value and write min.
  4. Move the file pointer to the minimum value and write max.

Below is the text of the program for solving the problem with comments.

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
setlocale (LC_ALL, «RUS»);
int n, i, imax, imin;
double *a, max, min;
FILE *f;
opening a file in read/write
mode f=fopen("D:\\game\\noobs.dat""rb+");
read from the file to the variable n the number of
real numbers in the file
fread(&n, sizeof(int),1, f);
cout<<"n="<<n<<endl;
allocate memory to store real numbers that
will be stored in the array a
=new double[n];
read the real numbers
fread(a, sizeof(double), n, f) from the file into the array a;
search for the maximum and minimum elements
in array a and their for indexes
(imax=imin=0, max=min=a[0], i=1; i<n; i++)
{
if (a[i]>max)
{
max=a[i];
imax=i;
}
if (a[i]<min)
{
min=a[i];
imin=i;
}
}
move the pointer to the maximum element
fseek(f, sizeof(int)+imax*sizeof(double)SEEK_SET);
record min instead of the maximum element of the file
fwrite(&min, sizeof(double)1, f);
move the pointer to minithe small element
fseek(f, sizeof(int)+imin*sizeof(double)SEEK_SET);
max entry instead of the minimum file
element fwrite(&max, sizeof(double),1, f);
Close the fclose(f) file
.
free memory
delete []a;
system(«pause»);
return 0
;
}

So, we've covered the basics of working with files in C++. In the following lessons, you will meet them again, so learn them as best as possible.