Программирование на С++. Файлы

Содержание

Слайд 2

Виды файлов в С(С++): Текстовые ; Двоичные (binary). Основные действия, производимые

Виды файлов в С(С++):
Текстовые ;
Двоичные (binary).
Основные действия, производимые над файлами:
открытие,


обработка,
закрытие.

Файлы

Слайд 3

Чаще всего под файлом понимают именованную совокупность данных на внешнем носителе

Чаще всего под файлом понимают именованную совокупность данных на внешнем носителе

информации.
В данной теме мы рассмотрим работу с дисковыми файлами.
Поток позволяет ассоциировать файл с буфером, который позволяет осуществить эффективный ввод - вывод. Буфер – это выделенный участок памяти. При буферном вводе информация с носителя информации (из файла) вначале поступает в буфер, а затем оттуда передается прикладной программе. Аналогично и при буферном выводе – информация из программы вначале поступает в буфер, а затем – на носитель информации (в файл).
Если для ввода и вывода в программе используются потоки, то для программиста буферизация выполняется автоматически.
В С (С++) различают два вида файлов : текстовые и двоичные (бинарные).
Текстовые файлы состоят из строк символов и предназначены для чтения человеком. На диске текстовые файлы хранятся в виде сплошной последовательности символов, и их деление на строки становится заметным лишь в момент вывода на экран или на печать, так как именно при выводе управляющие символы (например, \n) начинают выполнять свои функции.
Бинарный файл – это последовательность байтов, однозначно соответствующая последовательности байтов, записанной на внешнем устройстве.
Основными действиями, производимыми над файлами, являются их открытие, обработка и закрытие.

Файлы

Слайд 4

Файлы (С)

Файлы (С)

Слайд 5

Основные функции для работы с файлами (stdio.h) : Файлы (С )

Основные функции для работы с файлами (stdio.h) :

Файлы (С )

Слайд 6

Синтаксис объявления указателя на поток: #include FILE * имя указателя; Прототип

Синтаксис объявления указателя на поток:
#include
FILE * имя указателя;
Прототип функции fopen():
FILE

* fopen(const char *имя_файла, const char *режим_доступа)
Режимы доступа к файлам:

Файлы (С )

Слайд 7

Для управления потоками используются указатели. В языке С указатель на поток

Для управления потоками используются указатели.
В языке С указатель на поток

является указателем на тип с именем FILE.
Тип FILE определяется в заголовочном файле stdio.h и представляет собой структуру, описывающую параметры реализации потока, такие, например, как адрес буфера, с которым будет работать файл, адрес текущего символа, который будет передаваться (приниматься) в прикладную программу, и т. д..
При открытии файлов порция информации из дискового файла поступает в буфер и указатель на поток получает адрес буфера.
В языке С файлы открываю с помощью функции fopen(). Функция fopen() имеет два параметра. Первый параметра является строковой константой, которая задает имя файла и путь к нему. Второй параметр – тоже строковая константа – задает режим доступа к файлу. Режим доступа описывает две составляющие: способ доступа (чтение или запись) и тип файла (текстовый или двоичный).
Для работы с текстовым файлом можно к режиму доступа добавить строчную латинскую букву t, но делать это не обязательно, так как файлы открываются в текстовом виде по умолчанию.
Для работы с бинарными файлами обязательно нужно к режиму доступа добавить строчную латинскую букву b.

Файлы (С )

Слайд 8

Варианты открытия файла: Вариант 1: #include FILE *f; f = fopen("D:\\text.txt",

Варианты открытия файла:
Вариант 1: #include
FILE *f;
f =

fopen("D:\\text.txt", "r");
{ // обработка файла
}
Вариант 2: #include
FILE *f;
if((f = fopen("D:\\text.txt", "r"))!=NULL)
{ // обработка файла
}
Прототип функции fclose():
int fclose(FILE * f)

Файлы (С )

Слайд 9

Таким образом, чтобы открыть файл (например, текстовый файл) для чтения, нужно

Таким образом, чтобы открыть файл (например, текстовый файл) для чтения, нужно

произвести следующие действия :
Объявить указатель на поток;
Открыть файл функцией fopen() (т.е. связать указатель на поток с дисковым файлом и указать режим доступа r).
При попытке открыть существующий файл можно допустить ошибку в его имени или в указании пути к нужному файлу. Это вызывает ошибку выполнения программы. Следует предвидеть подобные ситуации и проводить проверку возможности открытия файла. Такую проверку осуществить довольно легко, так как функция fopen() возвращает значение указателя на поток в случае его успешного открытия и значение NULL (нулевой указатель), если доступ к файлу невозможен .
Файлы, открываемые в режиме записи, также нуждаются в аналогичной проверке.
Функция fclose() закрывает поток, открытый ранее функцией fopen(). Она записывает все оставшиеся в буфере данные в файл и закрывает его, используя команды операционной системы. Ошибка, возникшая при закрытии файла, может породить множество проблем, начиная с потери данных и разрушения файлов и заканчивая непредсказуемыми последствиями для программы. Кроме того, функция fclose() освобождает управляющий блок файла, связанного с потоком, позволяя использовать этот блок повторно.
Операционная система ограничивает количество одновременно открытых файлов, поэтому, прежде чем открыть один файл, следует закрыть другой.
Параметр f представляет собой указатель файла, возвращенный функцией fopen(). Если функция вернула нулевой указатель, значит, файл закрыт успешно. Как правило, функция fclose() выполняется неверно, если диск был преждевременно вынут из дисковода или переполнен.

Файлы (С )

Слайд 10

Функции ввода - вывода для обработки текстовых файлов: int fscanf (FILE

Функции ввода - вывода для обработки текстовых файлов:
int fscanf (FILE *stream,

форматная строка, список аргументов);
int fprintf (FILE *stream, форматная строка, список аргументов);
int fgetс(FILE *stream)
int fputс(char с, FILE *stream)
char *fgets(char *s, int size, FILE *stream)
int fputs(char *s, FILE *stream)

Файлы (С )

Слайд 11

Рассмотрим основные варианты обработки текстовых файлов. При работе с текстовыми файлами

Рассмотрим основные варианты обработки текстовых файлов.
При работе с текстовыми файлами возможна

их посимвольная или построчная обработка.
Функции fprintf() и fscanf() , fgetc() и fputc() используют для посимвольной обработки, а функции fgets() и fputs() для построчной обработки текстовых файлов.
Функции ввода-вывода fprintf() и fscanf() работают аналогчно функциям printf() и scanf(), но имеют дополнительный аргумент, являющийся указателем на файловый поток.
Функция fgetc () считывает символ из файла, открытого функцией fopen() в режиме чтения. Параметр stream является указателем на поток, возвращенным функцией fopen(). Функция fgetc() возвращает целочисленную переменную, младший байт которой содержит введенный символ. Если возникла ошибка, старший байт этой переменной равен нулю. Если при чтении обнаруживается конец файла, функция fgetc() возвращает константу EOF.
Функция fputc() записывает символ в файл, открытый с помощью функции fopen(). Параметр stream представляет собой указатель файла, возвращенный функцией fopen(), а аргумент является символом, подлежащим выводу. Указатель stream сообщает функции putc(), в какой именно файл следует произвести запись. Несмотря на то, что параметр имеет тип int, в файл записывается лишь младший байт. Если функция fputc() выполнена успешно, она возвращает символ, записанный ею в файл. В противном случае она возвращает константу EOF.
Функция fgets() считывает строку из size символов из потока stream, связанного с текстовым файлом, в строковую переменную s;
Функция fputs() записывает строку s в поток stream, связанный с текстовым файлом;

Файлы (С )

Слайд 12

Файлы (С ) Пример 1. Чтение элементов одномерного массива из текстового

Файлы (С )

Пример 1. Чтение элементов одномерного массива из текстового

файла и
запить в текстовый файл:
#include
#include
using namespace std;
int main(void)
{ int n = 0; int a[10];
FILE *f; // объявление потока
f = fopen("D:\\abc1.txt","r");
if (f) { cout << "Read file ! \n";
while(!feof(f))
{ fscanf(f,"%3d",&a[n]); // чтение из файла
n++;
} fclose(f);
for(int i=0;i < n;i++)
cout << a[i] << " ";
}
else cout << "File not found \n";
Слайд 13

Ввод – вывод элементов массива f = fopen("D:\\abc2.txt","w"); if (f) {

Ввод – вывод элементов массива
f = fopen("D:\\abc2.txt","w");
if (f)

{ for(int i = 0;i < n;i++)
fprintf(f,"%3d",a[i]); // запись в файл
cout << "\nFile write!";
fclose(f);
}
else cout << "File not found \n";
}
Слайд 14

Пример 2. Запись из исходного файла в выходной каждого третьего символа.

Пример 2. Запись из исходного файла в выходной каждого третьего символа.
#include


int main(void)
{ FILE * f_in, * f_out;
int k = 1;
int ch;
if ((f_in = fopen("D:\\text.txt","r"))!= NULL)
{ printf("Read and write file!\n");
f_out = fopen("D:\\text2.txt","w");
while((ch = fgetc(f_in))!= EOF)
if ((k++ % 3) == 0)
fputc(ch, f_out);
fclose(f_in); fclose(f_out);
}
else printf("Error open file!\n");
}

Файлы (С )

Слайд 15

Пример 3: //определить сколько чисел содержится в каждой строке тексто -

Пример 3:
//определить сколько чисел содержится в каждой строке тексто -
//вого файла.

Длина каждой строки не превышает 100 символов
#include
#include
#include
using namespace std;
int num(const char *str);
int main(void)
{ FILE * f; const int len = 101; int i = 1; char str[len];
f=fopen("D:\\FileTXT\\text3.txt","r");
if (f != NULL)
{ cout << "\nСколько чисел в каждой строке файла?";
while(!feof(f))
{ fgets(str,sizeof(str), f);
cout << "\nВ строке " << i << " - " << num(str);
i++;
} cout << endl;
} else cout << "Файл не найден!\n";
}

Строки и текстовые файлы

Слайд 16

int num(const char *str) { int count = 0; while (*str)

int num(const char *str)
{ int count = 0;
while (*str)

{if (isdigit(*str) && !isdigit(*(str + 1))
&& *(str + 1) !='.')
count ++;
str++;
}
return count;
}

Строки и текстовые файлы

Слайд 17

Открытие бинарного файла для чтения и записи: #include FILE *f; if((f

Открытие бинарного файла для чтения и записи:
#include
FILE *f;
if((f

= fopen("D:\\bin_file.dat", "r+b"))!= NULL)
{ // обработка файла
}
Открытие для записи (создание) бинарного файла:
#include
FILE *f;
if((f = fopen("D:\\bin_file.dat", "wb"))!= NULL)
{ // обработка файла
}
Функции ввода - вывода для обработки бинарных файлов:
size_t fread(const void *ptr, size_t site, size_t n, FILE *stream)
size_t fwrite(const void *ptr, size_t site, size_t n, FILE *stream)

Файлы (С )

Слайд 18

Способ хранения данных в бинарных (двоичных) файлах имеет два важных преимущества:

Способ хранения данных в бинарных (двоичных) файлах имеет два важных преимущества:
Увеличивается

скорость извлечения из файла данных, не носящих чисто текстового характера, так как не требуется действий по преобразованию их из текстового формата в двоичный.
Имеет место экономия памяти и дискового пространства, поскольку двоичная кодировка более компактна и нет необходимости в использовании управляющих символов.
Принципиально обработка двоичных файлов не очень сильно отличается от обработки текстовых файлов. В любом случае, прежде чем работать с файлом, следует открыть файл, указав режим доступа. Открыть файл для двоичной обработки можно посредством вызова функции fopen(), но ко всем режимам доступа добавляют строчную латинскую букву b. Режимы доступа одинаковы для текстовых и двоичных файлов. Если после вызова функции fopen() указатель на файловый поток f не равен нулю, его можно использовать в последующих обращениях к функциям работы с двоичными файлами, таким, как fwrite() и fread() . Закрывают двоичные файлы, как и текстовые, функцией fclose().
Функции fwrite() и fread() так же могут быть использованы для работы с текстовыми файлами, хотя чаще их используют для работы с бинарными файлами. Параметры функций:
ptr – указатель на исходные данные, читаемые из файла (записываемые в файл);
size – размер в байтах одного элемента данных;
Замечание. size_t – специальный идентификатор типа, который введен для обозначения типа результата, вычисляемого операцией sizeof. На самом деле идентификатор size_t является синонимом unsigned int.
n – число записываемых в файл элементов данных; stream – указатель на файловый поток.
Существует два способа доступа к элементам двоичных файлов: последовательный и произвольный.
Последовательный доступ к элементам файла особенно эффективен, если нужно перебрать все данные, хранящиеся в нем. Кроме того, если файл открыт для записи, но еще не содержит данных (т. е. пустой), то заполнение его возможно лишь в последовательном режиме.

Файлы (С )

Слайд 19

Ввод – вывод элементов массива Запить элементов одномерного массива в бинарный

Ввод – вывод элементов массива

Запить элементов одномерного массива в бинарный

файл и
чтение из бинарного файла:
#include
#include
using namespace std;
int main(void)
{ int n; int *a,*b;
FILE *f; // объявление потока
cout << "\n n = "; cin >> n; cout << "\n";
a = new int [n];
for (int i = 0; i < n; i++)
{ cout << "a[" << i << "]:"; cin >> a[i];
} cout << "\n";
f = fopen("D:\\abc3.dat","wb");
fwrite(&n,sizeof(int),1,f);
fwrite(a,sizeof(int),n, f);
fclose(f);
Слайд 20

Ввод – вывод элементов массива f = fopen("D:\\abc3.dat", "rb"); if (f)

Ввод – вывод элементов массива

f = fopen("D:\\abc3.dat", "rb");
if

(f)
{ fread(&n,sizeof(int),1, f);
b = new int [n];
fread(b, sizeof(int), n, f);
for (int i = 0; i < n; i++)
cout << b[i] << " ";
}
fclose(f);
}
Слайд 21

Произвольный доступ к элементам двоичных файлов Прототип функции fseek(): int fseek

Произвольный доступ к элементам двоичных файлов
Прототип функции fseek():
int fseek (FILE *stream,

long offset, int whence);
Значения аргумента whence :

Файлы (С )

Слайд 22

Организация произвольного доступа к компонентам файла позволяет считывать значения из любой

Организация произвольного доступа к компонентам файла позволяет считывать значения из любой

позиции в файле, а также записывать новую информацию в любое место в файле. Но к файлам с произвольным доступом предъявляется одно жесткое требование: их компоненты должны иметь одинаковую длину. Двоичные файлы позволяют обеспечить удовлетворение этого требования. О том, чтобы данные, которые будут находиться в файле произвольного доступа, имели одинаковый размер, следует позаботиться в момент создания файла.
Вспомним о том, что первичная запись в файл возможна только в режиме последовательного доступа.
Для организации произвольного доступа к элементам файла используют функцию fseek(), прототип которой описан в заголовочном файле stdio.h.
Функция fseek() перемещает внутренний указатель файлового потока, изменяя таким образом место в файле, с которого начинается следующая операция чтения или записи. В случае успешного завершения функция возвращает 0, в случае ошибки – ненулевое значение.
Параметры функции:
FILE *stream – указатель на открытый файловый поток;
long offset – число байтов, на которое нужно переместить файловый указатель в направлении, указанном параметром whence. Для перемещения файлового указателя в обратном направлении (в сторону начала файла) следует устанавливать offset равным отрицательному значению;
int whence – указывает положение точки отсчета файлового указателя, от которой будет происходить его перемещение Значения аргумента whence представлены в таблице.
При использовании функции fseek() следует соблюдать осторожность, так как попадание за пределы файла чаще всего не приводит к генерации ошибки, поэтому программисту самому следует принимать меры для предотвращения обращения к диску за пределами известных границ файла.

Файлы (С )

Слайд 23

Произвольный доступ к элементам двоичных файлов Прототип функции ftell(): long ftell

Произвольный доступ к элементам двоичных файлов
Прототип функции ftell():
long ftell (FILE *stream);
Операторы,

демотстрирующие возможности функции fseek() :
fseek (f, sizeof(t), SEEK_CUR); // с текущей позиции на
// следующую
fseek (f, -sizeof(t), SEEK_CUR); // на предыдущую
// позицию
fseek (f, 0, SEEK_END); //на конец файла

Файлы (С )

Слайд 24

При организации произвольного доступа используется функция ftell(), осуществляющая навигацию внутри файла.

При организации произвольного доступа используется функция ftell(), осуществляющая навигацию внутри файла.

Прототип функции описан в stdio.h. Данная функция возвращает внутренний указатель файлового потока, равный смещению в байтах от начала двоичного файла до байта, с которого начинается следующая операция ввода – вывода. Это значение можно передать функции fseek() .
Единственным параметром функции ftell() является указатель на открытый файловый поток.
Далее рассмотрим пример в котором организуется произвольный доступ к элементам двоичного файла.

Файлы (С )

Слайд 25

Произвольный доступ к элементам двоичных файлов Пример. Создать бинарный файл. В

Произвольный доступ к элементам двоичных файлов
Пример. Создать бинарный файл. В этом

файле записать 0 на место первого максимального элемента.
#include
#include
using namespace std;
void create(void);//прототип функции создания бинарного файла
void view(void);//прототип функции просмотра бинарного файла
void work(void);//прототип функции обработки бинарного файла
int main(void)
{ create(); // вызов функции создания бинарного файла
view(); // вызов функции просмотра бинарного файла
work(); // вызов функции обработки бинарного файла
view(); // вызов функции просмотра бинарного файла
}

Файлы (С )

Слайд 26

// определение функции создания бинарного файла void create(void) { FILE *

// определение функции создания бинарного файла
void create(void)
{ FILE * f; int

number, n;
if ((f = fopen("D:\\file.dat","wb"))!= NULL)
{ cout << " Enter quantity numbers n = ";
cin >> n;
cout << " \nEnter numbers : ";
for (int i = 0; i < n; i++)
{ cin >> number;
fwrite(&number,sizeof(int),1,f);
}
fclose(f);
}
else
printf("Error create file!\n");
}

Файлы (С )

Слайд 27

// определение функции просмотра бинарного файла void view(void) { int number;

// определение функции просмотра бинарного файла
void view(void)
{ int number;
FILE *

f;
if ((f = fopen("D:\\file.dat","rb"))!= NULL)
{ cout << "\nNumbers: ";
while (fread(&number,sizeof(int),1,f))
cout << number << " ";
cout << "\n";
fclose(f);
}
else printf("Error open file!\n");
}

Файлы (С )

Слайд 28

// определение функции обработки бинарного файла void work(void) { int number;

// определение функции обработки бинарного файла
void work(void)
{ int number; FILE *

f; int nom_max, max;
int zero = 0;int i = 0;
if ((f = fopen("D:\\file.dat","r+b"))!= NULL)
{ fread(&max,sizeof(int),1,f);
nom_max = 0; i++;
while (fread(&number,sizeof(int),1,f))
{ if (number > max)
{ max = number; nom_max = i;
}
i++;
}
fseek(f,nom_max*sizeof(int),SEEK_SET);
fwrite(&zero,sizeof(int),1,f);
fclose(f);
} else printf("Error open file!\n");
}

Файлы (С )

Слайд 29

Файлы (С++)

Файлы (С++)

Слайд 30

Синтаксис объявления потоков: #include ifstream имя_потока; // файловый поток ввода ofstream

Синтаксис объявления потоков:
#include
ifstream имя_потока; // файловый поток ввода
ofstream

имя_потока; // файловый поток вывода
fstream имя_потока; // файловый поток ввода и вывода
Прототип функции open():
void open(const char *name, int mode);
Режимы (mode) открытия файла:
ios::out – открытие файла для вывода;
ios::in – открытие файла для ввода;
ios::app – вводимые данные добавляются в конец файла;
ios::ate – вызывает поиск конца файла в момент открытия файла
ios::binary – открытие файла для бинарных операций.
ios::nocreate – когда открыт может быть только существующий файл;
ios::noreplace – невозможно открыть файл если он уже создан ранее
ios::trunk – уничтожение содержимого существующего файла до нуля
Синтаксис вызова функции open():
имя_потока.open(<фактические параметры>);

Файлы (С++ )

Слайд 31

В С++ для работы с файлами используются специальные потоки. Ресурсы работы

В С++ для работы с файлами используются специальные потоки. Ресурсы работы

с файловыми потоками находятся в заголовочном файле fstream.h.
В С++ используется три класса потоков: ввода, вывода и ввода-вывода.
После объявления потока его связывают с файлом с помощью функции open().
При вызове функции open() используется конструкция составного имени, так как функция open() является методом класса ios.

Файлы (С++ )

Слайд 32

Синтаксис определения файлового потока для вывода данных в файл: ofstream имя_потока(имя_файла,ios::out);

Синтаксис определения файлового потока для вывода данных в файл:
ofstream имя_потока(имя_файла,ios::out);
Синтаксис определения

файлового потока для ввода данных из файла:
ifstream имя_потока(имя_файла,ios::in);
Синтаксис определения файлового потока для добавления данных в конец файла:
ofstream имя_потока(имя_файла,ios::app);
Синтаксис чтения данных из файла:
Файловый_поток >> имена_переменных;
Синтаксис вывода данных в файл:
Файловый_поток << выводимые_данные;

Файлы (С++ )

Слайд 33

Можно производить связывание потока с именем файла сразу при его определении.

Можно производить связывание потока с именем файла сразу при его определении.

При этом сразу после имени потока указывается список фактических параметров.
Закрытие файлового потока выполняется с помощью встроенной функции close().
При вызове функции close() используется конструкция составного имени, так как функция close() является методом класса ios.
Ввод и вывод данных из (в) файла производится соответственно с помощью операторов извлечения (>>) и передачи данных в поток (<<).
Синтаксис чтения данных из файла аналогичен потоку cin. Синтаксис вывода данных в файл аналогичен потоку cout.
Замечание: Если в текстовом файле хранятся числовые значения, то после последнего числа не должно быть пробелов, символов табуляции и конца строки.

Файлы (С++ )

Слайд 34

Ввод – вывод элементов массива Чтение элементов одномерного массива из текстового

Ввод – вывод элементов массива

Чтение элементов одномерного массива из текстового

файла и
запить в текстовый файл (С++):
#include
#include
using namespace std;
int main(void)
{ int n = 0; int a[10];
ifstream f; // объявление потока для чтения
f.open("D:\\abc1.txt"); // режим ios::in
if (f) { cout << "Read file ! \n";
while(!f.eof())
{ f >> a[n]; // чтение из файла
n++;
} f.close();
for(int i=0;i < n;i++)
cout << a[i] << " ";
}
else cout << "File not found \n";
Слайд 35

Ввод – вывод элементов массива ofstream f2; // объявление потока для

Ввод – вывод элементов массива

ofstream f2; // объявление потока для

записи
f2.open("D:\\abc2.txt"); // режим ios::out
if (f)
{ for(int i = 0;i < n;i++)
f2 << a[i] << " "; // запись в файл
cout << "\nFile write!";
f2.close();
}
else cout << "File not found \n";
}