ПЗ_03 Файловый ввод/вывод
1 Цель занятия изучить основные способы файлового ввода и вывода данных в С и С++.
2 Краткие методические указания.Система ввода/вывода для описания процессов обмена информацией с внешними устройствами использует два понятия: поток данных и файл[Ш-192]. Поток описывает процесс взаимодействия – чтение, запись, строка, символ, а файл является абстрактным объектом, описывающим внешнее устройство. Для описания этого объекта используется специальная область, указатель на которую имеет типFILE. Перед началом работы с этим устройством (файлом) необходимо определить состояние этой области – выполнить своеобразный конструктор объекта файл – открыть файл. Для открытия файла используется специальная функция открытия файла, которая имеет следующий прототип:
FILE *fopen(const char *имя файла, const char *режим) – функция возвращает значение указателя на файл (область описывающую соответствующий объект), если файл удалось открыть и возвращает NULL, если открыть файл не удалось – не удалось выполнить конструктор этого объекта. Строка имя файла определяет имя или путь к открываемому файлу [Ш-192]. Строка режим определяет процесс взаимодействия потока данных с файлом. Определить причину не открытия файла можно выполнив функцию int ferror(FILE *fp), параметр которой fp указывает на открываемый файл.
В зависимости от типа внешнего устройства потоки, открываемые для файла функцией fopen могут иметь разные режимы работы. Эти режимы перечислены в таблице 9.2 [Ш-195]. Например, для устройства печати или экрана необходимо открыть поток для записи, так как на эти устройства данные только записываются. С устройства клавиатура можно только читать данные.
Потоки для файлов могут быть текстовыми или бинарными. Текстовый поток интерпретируется как поток символов, часть из которых могут управлять устройством. Коды текстовых (печатных) и управляющих символов приведены в таблице кодов символов ASCII. Для управления некоторыми устройствами в символьном потоке к коду 0х0А – новая строка, приписывается код 0х0D – возврат каретки. Поэтому передаваемая последовательность может оказаться короче потока поступившего на устройство. Если на устройство передается бинарный поток, то число переданных и принятых кодов совпадает. Ниже приведена программа записывающая в файл DATA.dt 256 первых натуральных чисел в режиме текстового потока.
// Fl_IO.cpp : Defines the entry point for the console application.
//Запись данных в символьный и бинарный файл
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
int _tmain(int argc, _TCHAR* argv[]){
FILE *fp;//Описываем указатель для описателя файла fp
if(!(fp=fopen("DATA.dt","w+"))){//Создание текстового файла
printf("File open is Err\n");//Сообщение об ошибке
return 1;//Прекращение работы при ошибке открытия файла
}
for(int i=0;i<256;i++)putc((char)i,fp);//Запись в файл
return 0;
}
Эта программа открывает в текущей директории программы текстовый файл для чтения и записи - DATA.dt и записывает в него 256 первых натуральных чисел. После завершения программы получен файл, показанный на рисунке 1, который содержит больше 256-ти чисел.
Рис 1. Текстовый файл для 256 первых натуральных чисел.
Добавление кода возврат каретки требуется для некоторых устройств печати. Для получения потока совпадающего с передаваемым необходимо использовать бинарный файл.
Для использования файла в программе необходимо проверять результат выполнения функции открытия файла. Если файл открыть не удалось, то функция fopen возвращает значение NULL. После открытия файла и его использования файл должен быть закрыт. Операционная система позволяет открывать ограниченное число файлов. Поэтому использованные файлы следует сразу закрывать. Закрытие файла производиться функцией int fclose(FILE *fp), которая возвращает NULL, если файл fp, открытый раннее, закрыт успешно.
В приведенной выше программе в файл записываются отдельные байты, представляющие первые 256 натуральных чисел. Для работы с текстовыми файлами в файлы можно записывать и читать из них строки символов [Ш-200]. Наиболее распространенные функции работы с файлами перечислены в таблице9.1 [Ш-194].
Для реализации файлового ввода/вывода в языке С++ необходимо к программе подключать заголовочные файлы классов:
- ifstream – для использования потоков ввода;
- ofstream– для использованияпотоков вывода;
- fstream– для использования потоков ввода и вывода.
В каждом из классов определены методы для работы с потоками и файлами, которые описаны в [Ш-438]. Для открытия файла (определения свойств потока и начального состояния файла) используется метод open. Прототип этого метода использует следующие параметры:
ifstream::open(const *filename, ios::mode); - где
filename – строка, определяющая путь к открываемому файлу;
mode – флаг режима открытия файла из родительского класса ios.
Флаги режимов в этом классе имеют следующие обозначения:
ios::app – данные из выходного потока записываются в конец файла:
ios::ate –при открытии указатель в конце файла, но его можно передвигать;
ios::binary –файл открывается в бинарном режиме;
ios::in – файл открывается для чтения (ввода из файла);
ios::out – файл открывается для записи (вывода в файл);
ios::trunk – при открытии старое содержимое файла уничтожается (очищается).
Например, для открытия на запись бинарного файла test из текущей директории необходимо выполнить следующий фрагмент программы:
ofstream outs;//Определяем поток вывода и
outs::open(“test”,ios::out | ios::binary);//открываем бинарный файл для этого потока.
Значения флагов режима открытия могут определяться по умолчанию [Ш-438]
Например, открытие текстового файлаtest на вывод, с учетом значений флагов по умолчанию можно выполнить следующим образом.
ofstream outs;//Определяем поток вывода и
outs::open(“test”);//открываем бинарный файл для этого потока.
Здесь используется значение флага ios::out, заданное для потока ofstream по умолчанию. Классы ifstream, ofstreamи fstreamсодержат конструкторы, которые открывают файлы. Поэтому текстовый файл test можно открыть на запись следующим образом
ofstream outs(“test”);
Если необходимо, в аргументах конструктора можно указать нужные флаги форматирования. Ниже приведена программа, которая печатает на экране коды своей
исполнительной программы.
//Печатает свой исполнительный файл
#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
setlocale(LC_ALL, "rus");//Установка кодовой таблицы для кириллицы
ifstream flpr(argv[0]);//Связываем поток ввода с файлом
if(!flpr){cout << "Не открывается указанный файл\n"; return 1;}
//Читаем символы из файла и печатаем
while(!flpr.eof())cout<< hex << flpr.get();
cout << endl;//Вывод символа перевод строки.
flpr.close();//Закрываем файл
return 0;
}
В эту программу включены интерфейсные файлы для использования файловой системы и ввода вывода. Оператор using определяет стандартное пространство имен. Перед исполнением программы необходимо в свойствах проекта указать путь к исходному коду программы. Обратите внимание, что пробелы являются разделителями строк в командной строке. Поэтому пути, в которых встречаются пробелы, надо заключать в кавычки. После успешного открытия файла выполняется цикл считывания (flpr.get()) и печати символов прочитанных из файла. Цикл завершается после окончания потока, который определяется функцией flpr.eof().
Для чтения и записи порций данных размер которых превышает один байт можно использовать функции [Ш-444] :
istream &read(char* bff, streamsize ln); - чтение из входного потока ln байт в буфер bff.
ostream &write(const char *bff, streamsize ln); - запись в выходной поток ln байт из bff.
Для определения ln размера буфера для размещения считанных данных в оперативной памяти необходимо воспользоваться функциями обеспечивающими произвольный доступ к элементам потока [Ш-450] seekg (seekр). Эта функция перемещает указатель к заданному элементу файла. Функция [Ш-453] tellg (tellp) позволяет определить позицию указателя. Следующий фрагмент программы позволяет определить длину файла fldata и прочитать его в выделенную для этого память:
streamsize LnData = 0;
flData.seekg(0,ios::end);//Определяем длину файла Data
LnData=flData.tellg();//в потоке ввода
BYTE* Pbff = static_cast<BYTE*>(malloc(LnData));//Выделение места для
ZeroMemory(Pbff,LnData);//очистка выделенного места
flData.seekg(0,ios::beg);//Возвращаем указатель позиции в начало потока
flData.read(Pbff,LnData);//Читаем значение из файла
В процессе обработки информации хранящейся в файле может потребоваться прочесть его содержимое целиком в память, а после этого обрабатывать, находящееся в памяти данные. Для размещения данных файла в оперативной памяти необходимо выделить место для этих данных. Объем данных в файле может быть разным. Поэтому возникает задача определения размера файла - числа байт в файле.
}
3 Порядок выполнения задания.
3.1 Изучить раздел Ввод/вывод на консоль [Ш-174]
3.2 Переработать программу «Запись данных..» так, что бы она записывала в файл то, что формируется. Указание - место сохранения надо открыть как бинарный файл. В отчете показать, что записывается ровно 256 кодов.
3.3 Разработать программу средствами языка С++, которая читает файл своего исходного кода и печатает его.
3.4 Изучить раздел «Файловая система» [Ш-438].
3.5 Разработать программу средствами языка С++, которая вводит вашу фамилию, имя и отчество (ФИО), записывает ФИО в файл указанный в командной строке, читает этот файл в символьный массив и печатает содержимое массива на экране. Программа должна реализовать следующий алгоритм:
П1. Вводит ФИО.
П2. Проверить указание используемого файла. Если файл не указан, то сообщить и завершить выполнение, иначе напечатать имя указанного файла.
П3. Открыть указанного файла на запись. Если файл не открыт, то сообщить и завершить выполнение, иначе сообщить об открытии файла.
П4. Запись в файл ФИО
П5. Закрыть файл .
П6 Открыть файл с ФИО на чтение. Если файл не открыт, то сообщить и завершить выполнение, иначе сообщить об открытии.
П7. Определить длину открытого для чтения файла и напечатать ее.
П8. Выделить в оперативной памяти место для размещения ФИО.
П9. Прочитать из открытого файла данные в массив, выделенный для ФИО.
П10. Напечатать прочитанные данные.
П11. Закрыть открытый файл.
П12. Завершить программу.
Разработку любой программы целесообразно начинать с разработки такого словесного алгоритма.
3.6 Результаты выполнения задания задокументировать в отчете.
Вопросы по теме занятия.
1 Как описывается процесс открытия файла.
2 Чем отличаются текстовые и бинарные файлы. Почему для обмена числовыми данными следует использовать бинарные файлы.
3 Как определяется результат выполнения файловых операций.
4 Почему открытые программой файлы должны быть закрыты после выполнения программы.
5 Как определить размер памяти, который необходимо выделить для чтения содержимого файла.
6 Как определить завершение файла при его чтении функцией get(s);.
Не нашли, что искали? Воспользуйтесь поиском по сайту:
©2015 - 2024 stydopedia.ru Все материалы защищены законодательством РФ.
|