Цель лекции: изучить понятия, характеристику и классификацию файлов и стандартных функций по работе с файлами, научиться решать задачи с использованием стандартных функций по работе с файлами на языке C++.
Файл – это
Часто бывает необходимо ввести некоторые данные из файла или вывести результаты в файл. Например, бывает необходимо обрабатывать массивы, которые слишком велики, чтобы полностью разместиться в памяти.
Файлы делятся на текстовые и двоичные.
Текстовый файл – это файл, в котором каждый символ из используемого набора символов хранится в виде одного байта (кода, соответствующего символу). Текстовые файлы разбиваются на несколько строк с помощью специального символа "конец строки". Текстовый файл заканчивается специальным символом "
Двоичный файл – файл, данные которого представлены в бинарном виде. При записи в двоичный файл символы и числа записываются в виде последовательности байт (в своем внутреннем
Особенностью языка С++ является отсутствие в нем структурированных файлов. Все файлы рассматриваются как неструктурированная последовательность байтов. При таком подходе понятие файла распространяется и на различные устройства.
В С++ существуют специальные средства ввода-вывода данных. Все
Поток – это абстрактное понятие, относящееся к любому переносу данных от источника к приемнику.
Функции библиотеки ввода-вывода языка С++, поддерживающие
Поток определяется как последовательность байтов и не зависит от конкретного устройства, с которым производится обмен (
(рис 19.1) Буферизация данных при работе с потокамиПри работе с потоком можно:
Когда программа начинает выполняться, автоматически открываются пять потоков, из которых основными являются:
stdin );stdout );stderr ).По умолчанию stdin ставится в соответствие клавиатура, а потокам stdout и stderr соответствует экран монитора.
В С++
Рассмотрим основные функции для работы с файлами в форматированном режиме.
Для работы с файлом в языке C++ необходима ссылка на файл. Для определения такой ссылки существует структура FILE, описанная в файле stdio.h. Данная структура содержит все необходимые поля для управления файлами, например: текущий указатель буфера, текущий счетчик байтов, базовый адрес буфера ввода-вывода, номер файла.
При открытии файла (потока) в программу возвращается указатель на поток (файловый указатель), являющийся указателем на объект FILE. Этот указатель идентифицирует поток во всех последующих операциях.
Например:
#include<stdio.h> .............. FILE *fp;
Для открытия файла существует функция , которая инициализирует файл.
Синтаксис:
fp=fopen(ИмяФайла, РежимОткрытия);
где fp – указатель на поток (файловый указатель);
ИмяФайла – указатель на строку символов, представляющую собой допустимое имя файла, в которое может входить спецификация файла (включает обозначение логического устройства, путь к файлу и собственно имя файла);
РежимОткрытия – указатель на
Например:
fp=fopen("t.txt","r");
Существуют несколько режимов открытия файлов.
| Режим | Описание | Начинается с... |
|---|---|---|
r |
Открывает текстовый файл для чтения. Если файл не существует, то выдается ошибка при исполнении программы. | начала |
w |
Открывает текстовый файл для записи. Если файл не существует, то он создается. Если файл уже существует, то удаляется его содержимое, файл перезаписывается | начала |
a |
Открывает текстовый файл для добавления. Если файл не существует, то он создается. Если существует, то содержимое из него не удаляется. | конца |
r+ |
Открывает текстовый файл для чтения и записи. Изменить размер файла нельзя. Если файл не существует, то выдается ошибка при исполнении программы. | начала |
w+ |
Открывает текстовый файл для чтения и записи. Если файл не существует, то он создается. Если файл уже существует, то удаляется его содержимое, файл перезаписывается. | начала |
a+ |
Открывает текстовый файл для чтения и записи. Если файл не существует, то он создается. Если существует, то содержимое из него не удаляется. | конца |
rb |
Открывает двоичный файл для чтения. Если файл не существует, то выдается ошибка при исполнении программы. | начала |
wb |
Открывает двоичный файл для записи. Если файл не существует, то он создается. Если файл уже существует, то удаляется его содержимое, файл перезаписывается. | начала |
ab |
Открывает двоичный файл для добавления. Если файл не существует, то он создается. Если существует, то содержимое из него не удаляется. | конца |
r+b |
Открывает двоичный файл для чтения и записи. Изменить размер файла нельзя. Если файл не существует, то выдается ошибка при исполнении программы. | начала |
rb+ |
||
w+b |
Открывает двоичный файл для чтения и записи. Если файл не существует, то он создается. Если файл уже существует, то удаляется его содержимое, файл перезаписывается. | начала |
wb+ |
||
a+b |
Открывает двоичный файл для чтения и записи. Если файл не существует, то он создается. Если существует, то содержимое из него не удаляется. | конца |
ab+ |
Поток можно открыть в текстовом ( t ) или двоичном ( b ) режиме. По умолчанию используется
"r+b" или "rb" – двоичный (бинарный) режим;
"r+t" или "rt" –
В файле stdio.h определена константа , которая сообщает об окончании файла (отрицательное целое число).
При открытии файла могут возникать следующие ошибки:
В этих случаях указатель на поток приобретет значение NULL (0). Указатель на поток, отличный от аварийного, не бывает равен NULL.
Для вывода сообщения об ошибке при открытии файла используется стандартная библиотечная функция из файла <stdio.h>:
void perror (const char*s);
Функция perror() выводит строку символов, адресуемую указателем s, за которой размещаются: двоеточие, пробел и сообщение об ошибке. Содержимое и формат сообщения определяются реализацией
Пример 1. Обнаружение и вывод ошибки при открытии файла.
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
FILE *fp;
if ((fp=fopen("t.txt", "r"))==NULL)
// выводит строку символов с сообщением об ошибке
perror("ошибка при открытии файла");
system("pause");
return 0;
}
Перед началом выполнения выполнилась успешно.
Открытые на диске файлы после окончания работы с ними рекомендуется закрыть явно. Это является хорошим тоном в программировании.
Синтаксис:
int fclose(УказательНаПоток);
Возвращает 0 при успешном -1 в противном случае.
Открытый файл можно открыть повторно (например, для изменения режима работы с ним) только после того, как файл будет закрыт с помощью функции fclose().
Синтаксис:
int remove(const char *filename);
Эта функция удаляет с диска файл, указатель на который хранится в . Функция возвращает ненулевое значение, если файл невозможно удалить.
Синтаксис:
int rename(const char *oldfilename, const char *newfilename);
Функция переименовывает файл; первый параметр – старое имя файла, второй – новое. Возвращает 0 при неудачном выполнении.
Для контроля достижения конца файла есть функция feof.
int feof(FILE * filename);
Функция возвращает ненулевое значение, если достигнут
1) Символьный ввод-вывод
Для символьного ввода-вывода используются функции:
int fgetc(FILE *fp);
где fp – указатель на поток, из которого выполняется считывание.
Функция возвращает int из потока fp. Если символ не может быть прочитан, то возвращается значение .
int fputc(int c, FILE*fp);
где fp – указатель на поток, в который выполняется запись;
c – переменная типа int, в которой содержится записываемый в поток символ.
Функция возвращает записанный в поток fp символ в формате int. Если символ не может быть записан, то возвращается значение .
Пример 2.
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
FILE *f;
int c;
char *filename="t.txt";
if ((f=fopen(filename,"r"))==0)
perror(filename);
else
while((c = fgetc(f)) != EOF)
putchar(c);
//вывод с на стандартное устройство вывода
fclose(f);
system("pause");
return 0;
}
2) Строковый ввод-вывод
Для построчного ввода-вывода используются следующие функции:
char *fgets(char *s, int n, FILE *f);
где char *s – адрес, по которому размещаются считанные байты;
int n – количество считанных байтов;
FILE *f – указатель на файл, из которого производится считывание.
Прием байтов заканчивается после передачи n-1 байтов или при получении '\n'. '\0'. При успешном завершении считывания функция возвращает указатель на прочитанную строку, при неуспешном – 0.
int fputs(char *s, FILE *f);
где char *s – адрес, из которого берутся записываемые в файл байты;
FILE *f – указатель на файл, в который производится запись.
'\0' ) в файл не записывается. Функция возвращает , если при записи в файл произошла ошибка, при успешной записи возвращает неотрицательное число.
Пример 3. Построчное копирование данных из файла f1.txt в файл f2.txt.
#include "stdafx.h"
#include <iostream>
using namespace std;
#define MAXLINE 255 //максимальная длина строки
int _tmain(int argc, _TCHAR* argv[]){
//копирование файла in в файл out
FILE *in, //исходный файл
*out; //принимающий файл
char buf[MAXLINE];
//строка, с помощью которой выполняется копирование
in=fopen("f1.txt","r");
//открыть исходный файл для чтения
out=fopen("f2.txt","w");
//открыть принимающий файл для записи
while(fgets(buf, MAXLINE, in)!=0)
//прочитать байты из файла in в строку buf
fputs(buf, out);
//записать байты из строки buf в файл out
fclose(in); //закрыть исходный файл
fclose(out);//закрыть принимающий файл
system("pause");
return 0;
}
3) Блоковый ввод-вывод
Для блокового ввода-вывода используются функции:
int fread(void *ptr, int size, int n, FILE *f);
где void * – указатель на область памяти, в которой размещаются считанные из файла данные;
int size – размер одного считываемого элемента;
int n – количество считываемых элементов;
FILE *f – указатель на файл, из которого производится считывание.
В случае успешного считывания функция возвращает количество считанных элементов, иначе – .
int fwrite(void *ptr ,int size, int n, FILE *f);
где void * – указатель на область памяти, в которой размещаются считанные из файла данные;
int size – размер одного записываемого элемента;
int n – количество записываемых элементов;
FILE *f – указатель на файл, в который производится запись.
В случае успешной записи функция возвращает количество записанных элементов, иначе – .
Пример 4.
#include "stdafx.h"
#include <iostream>
using namespace std;
struct Employee {char name[30];
char title[30];
float rate;
};
int _tmain(int argc, _TCHAR* argv[]){
Employee e;
FILE *f;
if((f=fopen("text.dat","w"))==NULL) {
printf("\nФайл не открыт для записи");
}
int n;
//запись в файл
printf("\nВведите количество записей N=");
scanf("%d",n);
for(int i=0;i<n;i++) {
//формируем структуру е
printf("имя:");scanf("%s",e.name);
printf("наименование:");scanf("%s",e.title);
printf("налог:");scanf("%f",e.rate);
//записываем е в файл
fwrite(e,sizeof(Employee),1,f);
}
fclose(f);
//чтение из файла
if((f=fopen("text.dat","rb"))==NULL)
printf("\nФайл не открыт для чтения");
while(fread(e,sizeof(Employee),1,f))
printf("%s, %s, %f;\n", e.name, e.title, e.rate);
fclose(f);
system("pause");
return 0;
}
4) Форматированный ввод-вывод
В некоторых случаях информацию удобно записывать в файл без преобразования, т.е. в символьном виде, пригодном для непосредственного отображения на экран. Для этого можно использовать функции форматированного ввода-вывода:
int fprintf(FILE *f, const char *fmt, ...);
где FILE*f – указатель на файл, в который производится запись;
const char * – форматная строка;
par1, par2, ... –
Функция возвращает число переменных, которым присвоено значение.
Пример 5.
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
FILE *f;
int n, nn,m;
if((f=fopen("int.dat","w"))==0)
perror("int.dat");
for(n=1;n<11;n++)
fprintf(f, "\n%d %d", n, n*n);
fclose(f);
if ((f=fopen("int.dat","r"))==0)
perror("int.dat");
m=1;
while(fscanf(f, "%d %d",n, nn) m++<11)
printf("\n%d %d",n,nn);
fclose(f);
system("pause");
return 0;
}
Порядок работы с текстовыми и двоичными файлами аналогичен.
Для записи данных в файл нужно выполнить:
FILE *.fopen .fprintf или fwrite.fclose.Для чтения данных из файла нужно выполнить:
FILE *.fopen .fscanf или fread .fclose.Пример 6. Написать программу, реализующую подсчет количества символов в заданном тексте и
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
int sum=0;
char c,file1[10],file2[10];
FILE *t,*g;
printf("Введите имя входного файла : ");
scanf("%s",file1);
printf("Введите имя выходного файла ");
scanf("%s",file2);
t=fopen(file1,"r");
g=fopen(file2,"w");
printf("\nСодержимое входного файла %s:\n",file1);
while(!feof(t)) {
c=getc(t);
if (c!=10 c!=-1)
//символы конца строки и конца файла не считаются
sum++;
printf("%c", c);
}
fprintf(g,"%d",sum);
printf("\nКоличество символов в тексте входного файла равно %d",sum);
fclose(t);
fclose(g);
system("pause");
return 0;
}
Буфер – это область оперативной памяти, предназначенная для временного хранения данных во время процессов ввода-вывода информации.
Двоичный файл – это файл, данные которого представлены в бинарном виде.
Извлечение из потока – это процесс
Помещение (включение) в поток – это процесс вывода данных в поток.
Поток – это абстрактное понятие, относящееся к любому переносу данных от источника к приемнику.
Режимы открытия файлов – это наборы допустимых действий с открываемыми в программе файлами.
Стандартные функции по работе с файлами – это функции из
Текстовый файл – это файл, в котором каждый символ из используемого набора символов хранится в виде одного байта (кода, соответствующего символу).
Файл – это
Файловый указатель – это указатель на объект FILE.
Цель работы: изучить понятия, характеристику и классификацию файлов и стандартных функций по работе с файлами, научиться решать задачи с использованием стандартных функций по работе с файлами на языке C++.
При выполнении лабораторной работы для каждого задания требуется написать программу на языке С++, которая получает на входе одну строковую величину, являющуюся корректным именем входного файла (при этом в программе следует предусмотреть проверку существования и корректности открытия файла). Ввод данных осуществляется из входного файла с учетом требований к входным данным, содержащихся в постановке задачи. Ограничениями на входные данные является максимальный размер строковых данных и допустимый диапазон числовых типов в языке С++. При некорректном открытии файла программа должна завершить работу с выдачей на экран соответствующего сообщения.
Теоретические сведения.
Ознакомьтесь с материалом лекции 19.
Задания к лабораторной работе.
Выполните приведенные ниже задания.
Указания к выполнению работы.
Каждое задание необходимо решить в соответствии с изученными методами обработки стандартных файлов в языке С++. В программном коде к каждой задаче следует выполнять
Следует реализовать каждое задание в соответствии с приведенными этапами:
Требования к отчету.
Отчет по лабораторной работе должен соответствовать следующей структуре.
Контрольные вопросы
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.