| Двоичный файл это последовательность
данных не текстового формата. Поэтому редактировать файл в текстовом редакторе
невозможно. С другой стороны такой файл может иметь меньший объем, а для
редактирования могут быть предназначены специальные редакторы. Чтение и запись потока байтов выполняют функции fread и fwrite. fread(void *buffer,
size, count, FILE *f); Функция считывает count элементов длиной size байтов в буфер, заданный указателем
buffer, из потока f. Функция возвращает количество прочитанных
элементов, которое может быть меньше count, если при чтении произошла ошибка или встретился конец
файла. fwrite(const void
*p, size, n, FILE *f); Функция записывает n элементов длиной size байт из буфера, заданного
указателем р, в поток f.
Возвращает число записанных элементов. Пример, демонстрирующий работу с этими функциями:   struct Client { int Num; char SurName[27]; char Name[21]; char SecName[21]; }; FILE *stream; Client AClient,
RClient; //Открываем файл для вывода if ((stream =
fopen("d:\\SAMPLE.DAT", "wb")) == NULL) { printf(RUS("Файл не открыт для
записи\n")); getch(); return 1; } AClient.Num = 1; strcpy(AClient.SurName,"Petrov"); strcpy(AClient.Name,
"Petr"); strcpy(AClient.SecName,
"Petrovich"); //Запись структуры в файл fwrite(&AClient,
sizeof(AClient), 1, stream); //Закрываем файл fclose (stream) ; //Открываем файл для чтения if ((stream = fopen
("d:\\SAMPLE.DAT ", "rb") ) == NULL) { printf (RUS("Файл не открыт для
чтения\n")) ; getch(); return 2 ; } fread(&RClient,
sizeof (RClient) , 1 , stream) ; //Закрываем файл fclose (stream) ; printf ("The
structure contains : \n "); printf ("Num =
%d SurName = %s Name = %s SecName = %s", RClient . Num ,
RClient . SurName , RClient . Name , RClient . SecName
) ;   В этом примере вначале файл открывается
для записи в него значений полей из структуры AClient, затем этот файл открывается для
чтения содержащейся в нем информации в структуру RClient. После чего поля этой структуры
выводятся на экран. При выполнении программа выводит на экран: The structure
contains: Num = 1 SurName =
Petrov Name = Petr SecName = Petrovich Операции ввода/вывода выполняются,
начиная с текущей позиции потока, определяемой положением (значением) указателя
потока. Указатель устанавливается при открытии на начало или конец файла (в
соответствии с режимом открытия ²a² ,²a+²) и изменяется
автоматически после каждой операции ввода/вывода. Текущее положение указателя
можно получить с помощью функций ftell и fgetpos
и задать явным образом с помощью функций fseek, fsetpos
и rewind. Эти функции
нельзя использовать для стандартных потоков. long int ftell(FILE *f); Функция возвращает текущую позицию в файле, связанном с потоком f, как длинное целое. В
случае ошибки она возвращает –1. int fgetpos(FILE *f, fpos_t *pos); Функция возвращает текущую позицию в файле, связанном с потоком f, и копирует значение по
адресу pos. Это
значение позднее может использоваться функцией fsetpos. Возвращаемое значение имеет тип
fpos_t. int fseek(FILE *f,
long off, int org); Функция перемещает текущую позицию в файле, связанном с потоком f, на позицию off, отсчитываемую от
значения org, которое
должно быть равно одной из трех констант, определенных в <stdio.h>: SEEK_CUR ( =1 ) – от текущей
позиции указателя; SEEK_END ( =2 ) – от конца файла; SEEK_SET ( =0 ) – от начала файла. Функция возвращает 0 , если указатель текущей позиции в файле успешно
изменен, и отличное от 0 значение в противном случае. int fsetpos(FILE
*f, const fpos_t *pos); Функция перемещает текущую позицию в файле, связанном с потоком f, на позицию *pos, предварительно
полученную с помощью функции fgetpos. void rewind(FILE *f); Функция очищает флаги ошибок в потоке f и устанавливает текущую позицию на начало
файла. Функции позиционирования позволяют провести вывод непосредственно
после ввода, не закрывая файл. Для этого их записывают между функциями ввода и
вывода. Однако рекомендуется всегда явным образом закрывать потоки, открытые
для записи, чтобы избежать потери данных. Рассмотрим пример, демонстрирующий работу этих функций:   struct Client { int Num; char SurName[27]; char Name[21]; char SecName[21]; }; FILE *stream; Client AClient,
RClient; //Открываем файл для вывода if ((stream =
fopen("d:\\SAMPLE.DAT", "wb")) == NULL) { printf(RUS("Файл не открыт для
записи\n")); getch(); return 1; } AClient.Num = 1; strcpy(AClient.SurName,"Petrov"); strcpy(AClient.Name,
"Petr"); strcpy(AClient.SecName,
"Petrovich"); //Запись структуры в файл fwrite(&AClient,
sizeof(AClient), 1, stream); long int pos =
ftell(stream); //Выводим позицию файла и длину структуры printf("The
file pos = %d structure length = %d\n", pos, sizeof(AClient)); //Репозиционируем файл rewind(stream); //Открываем файл для чтения if ((stream = fopen
("d:\\SAMPLE.DAT ", "rb") ) == NULL) { printf (RUS("Файл не открыт для
чтения\n")) ; getch(); return 2 ; } fread(&RClient,
sizeof (RClient) , 1 , stream) ; //Закрываем файл fclose (stream) ; printf ("The
structure contains : \n "); printf ("Num =
%d SurName = %s Name = %s SecName = %s", RClient . Num ,
RClient . SurName , RClient . Name , RClient . SecName
) ;   Этот пример представляет собой
модификацию предыдущего примера. Здесь файл открывается лишь однажды, и после
записи в него структуры на экран выводится значение указателя позиции и длины
структуры. При выполнении программа выводит на экран: The file pos
= 76 structure length
= 76 The structure
contains: Num = 1 SurName =
Petrov Name = Petr SecName = Petrovich Допустим, что в файле хранятся сведения о
мониторах. В каждой строке указан тип, оптовая и розничная цены и примечание.
Для простоты данные в каждой строке записаны единообразно: первые 20 символов
занимает тип монитора, далее по 5 символов целые числа, представляющие оптовую
и розничную цены, затем примечание длиной не более 40 символов. Приведенная ниже программа построчно
считывает данные из текстового файла в буферную переменную s, затем формирует из них структуру mon и записывает ее в двоичном
режиме в выходной файл. Далее производится считывание из этого файла
произвольной записи.   FILE *fi, *fo; if((fi =
fopen("d:\\file.txt", "r")) == 0){ cout
<< "Ошибка открытия входного файла"; return 1;} if((fo =
fopen("d:\\binfile.out", "w+b")) == 0){ cout
<< "Ошибка открытия выходного файла"; return 1;} const int dl = 80; char   s[dl]; struct{ char type[20]; int  opt, rozn; char comm[40];  }mon; int kol
= 0; // Количество записей в файле while (fgets(s, dl, fi))  // Преобразование строки в структуру: { strncpy(mon.type,
s, 19); mon.type[19]='\0'; mon.opt =
atoi(&s[20]); mon.rozn =
atoi(&s[25]); strncpy(mon.comm,
&s[30], 40); fwrite(&mon,
sizeof mon, 1, fo); kol++; } fclose(fi); int i; cout
<< RUS("\nВведите номер записи
"); cin >>
i;  // Номер записи if (i >= kol) {cout << "Запись не существует"; return 1;} // Установка указателя текущей позиции файла на запись i: fseek(fo, (sizeof
mon)*i , SEEK_SET); fread(&mon,
sizeof mon, 1, fo); cout <<
"mon. type " << mon.type << " opt " <<
mon.opt << "
rozn " << mon.rozn << endl ; fclose(fo); |