[H-L-L.ru] |
Форма входа |
Меню сайта |
Главная » Статьи » Лекции по C++ » 12. Потоки ввода/вывода |
Двоичный файл это последовательность данных не текстового формата. Поэтому редактировать файл в текстовом редакторе невозможно. С другой стороны такой файл может иметь меньший объем, а для редактирования могут быть предназначены специальные редакторы. Чтение и запись потока байтов выполняют функции 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); Источник: функции позиционирования c++ пример работы с потоками fread fwrite двоичный файл | |
Всего комментариев: 0 | |