[H-L-L.ru]

Форма входа

Меню сайта

Categories
1. Основы работы в среде C++ Builder.Основы языка Си++ [9]
2. Операторы ветвления и операторы передачи управления [4]
3. Операторы цикла и операторы передачи управления [5]
4. Одномерные массивы [3]
5. Многомерные массивы [3]
6. Указатели.Динамическое распределение памяти [6]
7. Отладка программы [3]
8. Функции [8]
9. Строки [5]
10. Функция Main [2]
11. Типы данных,определяемые пользователем [5]
12. Потоки ввода/вывода [7]
13. Основы объектно-ориентированного программирования [5]
Приложения [11]

Главная » Статьи » Лекции по C++ » 12. Потоки ввода/вывода

6. Функция ввода/вывода fread и fwrite

Двоичный файл это последовательность данных не текстового формата. Поэтому редактировать файл в текстовом редакторе невозможно. С другой стороны такой файл может иметь меньший объем, а для редактирования могут быть предназначены специальные редакторы.

Чтение и запись потока байтов выполняют функции 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
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]

Полная версия сайта