
Лекция 10 - Потоки и файлы.ppt
- Количество слайдов: 28
Информатика и программирование Потоки и файлы Полежаев Петр Николаевич
Понятие потока Поток – абстрактное понятие, относящееся к любому переносу данных от источника к приемнику. Поток определяется как последовательность байтов и не зависит от конкретного устройства, с которым производится обмен данными (например, с оперативной памятью, файлом на диске, клавиатурой, экраном, принтером и пр. ). Чтение данных из потока называется извлечением, вывод в поток – помещением.
Виды потоков По направлению обмена потоки делятся на: • входные – данные вводятся в оперативную память; • выходные – данные выводятся из оперативной памяти; • двунаправленные – допускается ввод и вывод данных из памяти.
Виды потоков По виду устройства, с которым работает поток, можно разделить потоки на: стандартные – предназначены для передачи данных от клавиатуры и вывода информации на экран; файловые – предназначены чтения и записи данных в файл; строковые – для работы с массивами символов в оперативной памяти.
Работа с потоками в С++ может осуществляться двумя способами: 1. С помощью функций ввода-вывода, унаследованных от языка С. 2. С помощью потоковых классов (в стиле С++).
Понятие файла Файл – поименованная область на носителе информации, представляющая собой цельный объект, используемый для хранения некоторого набора данных. Различают полные и короткие имена файлов. Короткое имя файла состоит из его названия и расширения. Пример: file. txt Полное имя включает путь доступа к файлу. Пример: C: StudentLec 10file. txt
Последовательность действий по работе с файлами 1. Открытие файла – выделение ресурсов в программе и приведение файла в состояние готовности к обмену. 2. Выполнение серии операций чтения (ввода из файла) или записи (вывода в файл) порций данных 3. Закрытие файла – освобождение выделенных ресурсов и завершение оконченных операций.
Работа с файлами с помощью функций, унаследованных из С Для работы с файлами (потоками) в стиле языка С необходимо подключить заголовочный файл
Открытие файла осуществляется с помощью функции fopen: FILE* fopen (const char* filename, const char* mode); Параметры: filename – имя файла; mode – строка, указывающая режим открытия файла: “r” – файл открывается для чтения; “w” –открывается пустой файл для записи; “a” – файл открывается для добавления в его конец; “r+” – файл открывается для чтения и записи; “w+” –открывается пустой файл для чтения и записи; “a+” – файл открывается для чтения и добавления в его конец. По умолчанию открываются текстовые файлы. Если необходимо открыть двоичный файл, то добавляется символ «b» . Например, режим “wb+” означает открытие пустого двоичного файла для чтения и записи. Возвращаемое значение - указатель на структуру FILE, который необходимо присвоить файловой переменной для дальнейшей работы с файлом. Или NULL, если файл не удалось открыть. Пример: FILE* fp = fopen(“C: \lab 10\input. info”, “rb+”);
Закрытие файла По окончанию работы с файлом его необходимо закрыть. При этом освобождается память, занимаемая структурой FILE, на которую указывает файловая переменная. А также сохраняет содержимое буфера, используемого для буферизации ввода/вывода. Для этого вызывается функция fclose: int fclose(FILE * fp); Если функция вернула NULL, то файл был успешно закрыт. Пример: fclose(fp);
Буферизация ввода/вывода При вводе или выводе информации в файл используется промежуточный буфер – некоторая область оперативной памяти, связываемая с файлом при его открытии. При записи данных, они сначала помещаются в буфер, как только буфер полностью наполняется, его содержимое сбрасывается в файл во внешней памяти. Аналогично при чтении данных, они сначала помещаются в буфер, а потом из него читает программа. Данный подход называется буферизованным вводом/выводом. Использование буфера ускоряет работу с устройствами внешней памяти. Буферизация данных в принципе происходит для программиста прозрачно, и он может о ней не задумываться.
Функции ввода/вывода • • Функции чтения и записи символа Функции чтения и записи строки Функции чтения и записи потока байт Функции форматного ввода и вывода данных в файл
Функции чтения и записи символа Функция чтения символа из потока, связанного с файловой переменной fp: int fgetc(FILE* fp); Если достигнут конец файла, то функция вернет значение EOF, иначе – код считанного символа. Функция записи символа ch в поток, связанный с файловой переменной fp: int fputc(int ch, FILE* fp); В случае успеха функция возвращает записанный символ, иначе – значение EOF.
Пример …… char ch; FILE* fp; //Файловая переменная //Открываем текстовый файл "output. txt" на запись fp = fopen("output. txt", "w"); do { //Читаем с клавиатуры очередной символ ch = cin. get(); //Выводим его в файл fputc(ch, fp); //Цикл заканчивается, когда с клавиатуры //будет введен символ '@‘ } while (ch != '@'); //Закрываем файл fclose(fp); ……
Функции чтения и записи строки Функция чтения строки str из потока, связанного с файловой переменной fp: char* fgets(char* str, int leng, FILE* fp); Функция читает из потока символы, пока не обнаружит символ перевода строки или не прочитает leng-1 символов. Возвращаемое значение – в случае успеха указатель на введенную строку, иначе (например, когда достигнут конец файла) – нулевой указатель. Функция записи строки str в поток, связанный с файловой переменной fp: char* fputs(const char* str, FILE* fp); При возникновении ошибки функция возвращает EOF.
Пример …… char s[MAX_LENGTH + 1]; //Файловая переменная FILE * fp; //Открываем текстовый файл "input. txt" на чтение fp = fopen("input. txt", "r"); //Читаем очередную строку, пока не достигли конца файла while (fgets(s, sizeof s, fp)) { //Выводим ее на экран cout << s; } //Закрываем файл fclose(fp); ……
Функции чтения и записи потока байт Функция чтения потока байт в буфер из файла: size_t fread(void* buf, size_t blocksize, size_t count, FILE* fp); Функция записи потока байт из буфера в файл: size_t fwrite(void* buf, size_t blocksize, size_t count, FILE* fp); Параметры: buf – указатель на void, определяет адрес начала буфера, содержащего вводимые/выводимые блоки данных; blocksize – размер одного блока данных; count – количество блоков данных; fp – файловая переменная. Возвращаемые значения - количество введенных/выведенных блоков данных.
Пример struct Employee //Сотрудник { char Surname[MAX_LENGTH]; //Фамилия int Age; //Возраст double Salary; //Зарплата }; //Функция, загружающая из файла с именем file_name сведения обо всех сотрудниках и сохраняющая их в массив emps, а количество в переменную emp_cnt void Load. Employees(Employee emps[], int& emp_cnt, const char* file_name) { FILE* fp; //Файловая переменная //Открываем двоичный файл на чтение fp = fopen(file_name, "rb"); //Читаем количество сотрудников fread(&emp_cnt, sizeof emp_cnt, 1, fp); //Читаем всех сотрудников fread(emps, sizeof emps[0], emp_cnt, fp); fclose(fp); //Закрываем файл }
Функции форматного ввода/вывода Функция форматного ввода: int fscanf(FILE* fp, const char*format, …); Функция форматного вывода: int fprintf(FILE* fp, const char*format, …); Параметры: fp – файловая переменная; format – строка форматирования; … - вводимые/выводимые параметры. Данные функции аналогичны функциям scanf/printf, используемым для ввода/вывода информации на консоль.
Пример double mat[MAX_SIZE]; int nrows, ncols; double sum; //Открываем текстовый файл "input. txt" на чтение FILE *fin = fopen("input. txt", "r"); //Открываем текстовый файл "output. txt" на запись FILE *fout = fopen("output. txt", "w"); //Читаем из входного файла размеры метрицы fscanf(fin, "%d%dn", &nrows, &ncols); for (int i = 0; i < nrows; i++) { sum = 0. 0; for (int j = 0; j < ncols; j++) { //Читаем из входного файла очередной элемент матрицы fscanf(fin, "%lf", &mat[i][j]); sum += mat[i][j]; } //Выводим в выходной файл сумму элементов i-й строки матрицы fprintf(fout, "sum of elements int row %d : %lfn", i, sum); } fclose(fin); fclose(fout); //Закрываем файлы
Определение конца файла Для определения достигнут ли конец файла используется функция feof: int feof(FILE* fp); Если достигнут конец файла, то функция возвращает ненулевое значение, иначе 0.
Пример …… char s[MAX_LENGTH + 1]; FILE * fp; //Файловая переменная //Открываем текстовый файл "input. txt" на чтение fp = fopen("input. txt", "r"); do { //Читаем очередную строку, fgets(s, sizeof s, fp); //Если не достигли конца файла, то выводим на //экран считанную строку if (!feof(fp)) cout << s; //Пока не достигли конца файла } while (!feof(fp)); //Закрываем файл fclose(fp); ……
Указатель потока Файловые операции ввода/вывода выполняются начиная с текущей позиции потока, определяемой положением указателя потока. При открытии файла указатель автоматически устанавливается на начало или конец файла (последнее в случае открытия в режиме добавления в конец). Положение указателя потока изменяется автоматически при выполнении каждой операции ввода/вывода.
Функции для работы с указателем потока Функция чтения позиции указателя в потоке fp: long ftell(FILE* fp); Функция установки позиции указателя в потоке int fseek(FILE* fp, long offset, int origin); Параметры: fp – файловая переменная; offset – смещение, определяющее количество байт на которое нужно переместить указатель от точки, заданной параметром origin; origin – задается одним из следующих макросов: SEEK_SET – начало файла; SEEK_CUR – текущая позиция; SEEK_END – конец файла. В случае успеха функция возвращает 0, иначе ненулевое значение.
Работа с файлами в стиле С++ Для работы с файлами в языке С++ предусмотрены потоковые классы: ifstream – класс входного файлового потока; ofstream – класс выходного файлового потока; fstream – класс двунаправленного файлового потока. Чтобы использовать данные классы необходимо подключить заголовочный файл
Пример double mat[MAX_SIZE]; int nrows, ncols; double sum; //Описываем поток ввода и связываем его с файлом "input. txt“ ifstream inp("input. txt"); //Описываем поток вывода и связываем его с файлом "output. txt“ ofstream out("output. txt"); inp >> nrows >> ncols; //Считываем размеры матрицы for (int i = 0; i < nrows; i++) { sum = 0. 0; for (int j = 0; j < ncols; j++) { inp >> mat[i][j]; //Читаем очередной элемент матрицы sum += mat[i][j]; } //Выводим в выходной файл сумму элементов i-й строки матрицы out << "sum of elements int row " << i << " : " << sum << endl; } inp. close(); out. close(); //Закрываем файловые потоки
Домашнее задание • Выписать все функции для работы с файлами в С-стиле • Выписать и выучить спецификации формата для функций fprintf/fscanf (см. Павловская "Программирование на языке высокого уровня", Приложение 2, с. 387 - 389). • Самостоятельно изучить и кратко законспектировать принципы работы с потоками в С++ - стиле (см. Павловская "Программирование на языке высокого уровня «, с. 265 -282).
Вопросы? • Q&A