Реферат Курсовая Конспект
Лекция 29-30 - Лекция, раздел Информатика, Лекция 29-30 Потоковый Ввод-Вывод ...
|
Потоковый ввод-вывод
Поток – это программный канал для обмена данными между приложением и ОС или другим приложением. При взаимодействии приложения с ОС потоки как правило используются для работы с устройствами и представляют собой абстрактный уровень между приложением и устройством, что позволяет скрыть от приложения низкоуровневый механизм доступа к устройствам (их системы команд, порты) и упростить и унифицировать процесс написания программ. Поток представляется программисту как логическое устройство приёма-передачи информации. Потоки бывают входные, выходные и двунаправленные.
Данные, поступающие в поток, как правило, буферизуются, то есть помещаются в специальный буфер данных, в котором они могут храниться. Передача данных из буфера получателю данных происходит при запросе от получателя или в случае заполнения буфера данных. Если получатель производит чтение данных, когда буфер потока пуст, то данная ситуация расценивается как достижение конца потока, как правило функции, работающие с потоками, в данном случае возвращают константу EOF (равную -1), определённую в файле stdio.h.
Существуют два основных типа ввода-вывода: форматированный и неформатированный. При форматированном вводе-выводе производится преобразование типов и структуры данных. При неформатированном вводе-выводе подобное преобразование не производится. Например, при форматированном выводе числа типа float функцией printf() можно задавать форму отображения числа на экране. Форматированный и неформатированный ввод-вывод выполняется соответствующими функциями ввода-вывода.
Поток для работы может быть отрыт в текстовом или бинарном режиме. Если поток открыт в текстовом режиме, то нет однозначного соответствия между данными, помещаемыми в поток, и данными, извлекаемыми из потока (например, символ ‘n’ при выводе на экран преобразуется в пару символов: перевод строки и возврат каретки, а символ ‘Ctrl+Z’ интерпретируется как EOF). Если поток открыт в бинарном режиме, то данные, помещаемые в поток, однозначно соответствуют данным, извлекаемым из потока. Это существенно при работе с символьной информацией, содержащей escape-последовательности.
С потоками можно производить следующие действия: открывать и закрывать потоки; посылать данные в поток и получать данные из потока; анализировать ошибки потокового ввода-вывода; управлять буферизацией потока и размером буфера; позиционировать указатель чтения-записи данных в потоке (если возможно).
Все потоки и функции для работы с ними объявлены в файле stdio.h.
Понятие «файл» в языке C несколько отличается от общепринятого в информатике. Под «файлом» понимается некоторое устройство, работа с которым организуется через поток (это может быть и файл на диске). Файл определяет способ хранения информации на физическом устройстве, поэтому файлы бывают различные, в отличии от потоков, которые одинаковы. Например, если под «файлом» понимается файл на диске, то можно производить произвольный доступ к любому байту файла, если же под «файлом» понимается принтер, до будет возможен только последовательный обмен данными.
Отличие потока от файла заключается в том, что поток представляет собой абстрактный уровень доступа программиста к физическому устройству, а файл представляет собой способ хранения информации на этом физическом устройстве.
Операция открытия файла связывает поток с определённым файлом, операция закрытия разрывает эту связь. Каждый поток, связанный с файлом, имеет управляющую структуру типа FILE. Указатель на данную структуру, называемый также указателем на файловую переменную, является связующим звеном между потоком и файлом, работа с потоком, а значит, и со связанным с ним файлом, осуществляется через связанный с потоком указатель на файловую переменную. Работа с потоком, который не связан ни с каким файлом, либо невозможна, либо может привести к неправильной работе как программы, так и системы в целом.
Указатель на файловую переменную.
В заголовочном файле stdio.h следующая структура объявлена как файловая переменная:
typedef struct {
int level;
unsigned flags;
char fd;
unsigned char hold;
int bsize;
unsigned char *buffer;
unsigned char *curp;
unsigned istemp;
short token;
} FILE;
Поле level определяет состояние буфера (пуст, полон), поле flags – флаги состояния файла, поле fd – дескриптор (префикс) файла, поле hold – непереданный символ, поле bsize – размер внутреннего буфера, поле buffer – указатель на буфер данных, поле curp – текущий указатель чтения-записи файла, поле istemp – флаг временного файла, поле token – права доступа к файлу. Поле flags может иметь следующие значения, определенные как макросы.
Макрос | Значение | Пояснение |
_F_RDWR | 0x0003 | Файл открыт для чтения и записи |
_F_READ | 0x0001 | Файл открыт только для чтения |
_F_WRIT | 0x0002 | Файл открыт только для записи |
_F_BUF | 0x0004 | Имеется буфер данных |
_F_LBUF | 0x0008 | Построчно буферизуемый файл |
_F_ERR | 0x0010 | Индикатор ошибки |
_F_EOF | 0x0020 | Индикатор EOF |
_F_BIN | 0x0040 | Индикатор бинарного файла |
_F_IN | 0x0080 | Буфер содержит входные данные |
_F_OUT | 0x0100 | Буфер содержит выходные данные |
_F_TERM | 0x0200 | Файл является терминалом |
Функции для работы с файлами.
FILE * fopen(const char * path, const char * mode);
Функция открывает файл, имя которого принимает в качестве параметра path, и связывает его с потоком. В случае успеха функция возвращает указатель на файловую переменную, в случае ошибки – NULL. Параметр mode задает режим открытия файла.
Режим | Действие |
«r» | Открыть существующий файл для чтения (файл должен существовать на диске). Указатель чтения-записи устанавливается в начало файла. |
«w» | Открыть существующий (содержимое при открытии теряется) или создать новый файл для записи. Указатель чтения-записи устанавливается в начало файла, при закрытии размер файла усекается по размеру до текущей позиции указателя. |
«a» | Открыть существующий или создать новый файл для добавления (запись в конец файла). Указатель чтения-записи устанавливается в конец файла. |
«r+» | Открыть файл для чтения и записи. Указатель чтения-записи устанавливается в начало файла. При закрытии файла размер не усекается. |
«w+» | Создать или открыть файл для чтения и записи, если файл существует, он перезаписывается. Указатель чтения-записи устанавливается в начало файла. При закрытии файла размер усекается. |
«a+» | Создать или открыть файл для добавления для чтения и записи. Указатель чтения-записи устанавливается в конец файла. При закрытии файла размер не усекается. |
«rb» | Аналогично «r», бинарный режим |
«wb» | Аналогично «w», бинарный режим |
«ab» | Аналогично «a», бинарный режим |
«r+b» | Аналогично «r+», бинарный режим |
«w+b» | Аналогично «w+», бинарный режим |
«a+b» | Аналогично «a+», бинарный режим |
«rt» | Аналогично «r», текстовый режим |
«wt» | Аналогично «w», текстовый режим |
«at» | Аналогично «a», текстовый режим |
«r+t» | Аналогично «r+», текстовый режим |
«w+t» | Аналогично «w+», текстовый режим |
«a+t» | Аналогично «a+», текстовый режим |
Если текстовый или бинарный режим не задан явно, он устанавливается по умолчанию в зависимости от значения внешней переменной _fmode.
Возвращаемый функцией указатель всегда следует проверять на равенство константе NULL (как и при использовании динамического распределения памяти).
FILE * freopen(const char * path, const char * mode, FILE * stream);
Функция закрывает поток stream и открывает файл, имя которого принимает в качестве параметра path, и связывает его с потоком. В случае успеха функция возвращает указатель на файловую переменную, в случае ошибки – NULL. Параметр mode задает режим открытия файла. Данная функция может быть использована для перенаправления стандартных потоков.
FILE * tmpfile(void);
Открывает временный файл с правами доступа «w+b», который можно закрывать, а можно и не закрывать – при завершении программа сама автоматически закроет его. В случае успеха функция возвращает указатель на файловую переменную, в случае ошибки – NULL.
int rmtmp(void);
Функция закрывает и удаляет все открытые временные файловые потоки. Возвращает число закрытых и удалённых файловых потоков.
int fflush(FILE * stream);
Функция выполняет передачу данных из внутреннего буфера файла stream на устройство. Функция возвращает 0, если операция прошла успешно, и EOF в случае ошибки. Данная операция необходима, чтобы предотвратить потерю данных в буфере в случае внезапного сбоя системы.
int flushall(void);
Функция выполняет передачу данных из внутренних буферов всех файлов и возвращает общее число входных и выходных потоков.
int unlink(const char* filename);
Функция удаляет файл filename, имя файла должно быть абсолютным. Файл, имеющий атрибут read-only, не может быть удалён данной функцией. Кроме того, не может быть удалён открытый файл (его нужно предварительно закрыть). В случае успеха, функция возвращает 0, в случае ошибки функция возвращает –1 и устанавливает значение переменной errno в одно из следующих значений: ENOENT – файл не существует, EACCES – нет прав доступа.
int remove(const char* filename);
Макрос, выполняющий вызов функции unlink(). Аналогичен функции unlink().
int rename(const char* oldname, const char* newname);
Функция переименовывает файл oldname в файл newname. В случае успеха функция возвращает 0, в случае ошибки функция возвращает –1 и устанавливает значение переменной errno в одно из следующих значений: ENOENT – файл не существует, EACCES – нет прав доступа, ENOTSAM – неверно задано устройство.
void setbuf(FILE * stream, char * buf);
Функция задает для файла stream область памяти, которая будет использоваться под буфер. Адрес начала буфера передается в качестве параметра buf, который должен быть указателем на блок памяти размером BUFSIZ (макрос, результат макрорасширения – 512). Если buf==NULL, то обмен данными будет небуферирован. По умолчанию для обычных файлов используется буфер размером 512 байтов, для стандартных потоков – 128 байтов.
int setvbuf(FILE * stream, char * buf, int type, size_t size);
Функция задает для файла stream область памяти, которая будет использоваться под буфер. Адрес начала буфера передается в качестве параметра buf, который должен быть указателем на блок памяти размером size (0<size<32K). Параметр type определяет способ буферизации и может иметь следующие значения, определенные как макросы.
Макрос | Значение | Способ буферизации |
_IOFBF | Полная буферизация, если buf==NULL, то функция сама выделяет буфер размером size | |
_IOLBF | Построчная буферизация | |
_IONBF | Буферизация отсутствует |
void rewind(FILE * stream);
Функция устанавливает указатель чтения-записи в начало файла (потока) stream.
int fseek(FILE * stream, long offset, int whence);
Функция позиционирует указатель чтения-записи для потока stream на offset байтов от точки отсчёта, задаваемой параметром whence. Для задания точки отсчёта определены следующие макросы.
Макрос | Значение | Точка отсчёта |
SEEK_SET | Начало файла | |
SEEK_CUR | Текущая позиция | |
SEEK_END | Конец файла |
В случае успеха функция возвращает 0, в случае ошибки – значение, отличное от 0.
long ftell(FILE * stream);
Функция возвращает в случае успеха смещение текущей позиции указателя чтения- записи для файла stream от начала файла, в случае ошибки -1L.
int fclose(FILE * stream);
Функция выполняет закрытие файла stream, при этом происходит освобождение буфера. Функция возвращает 0, если операция закрытия прошла успешно, и EOF в случае ошибки.
int fcloseall(void);
Функция выполняет закрытие всех открытых файлов и возвращает число закрытых файлов, если операция закрытия прошла успешно, и EOF в случае ошибки.
int feof(FILE * fp);
Макрос feof() выполняет проверку, достигнут ли конец файла (потока) fp, и возвращает 0, если конец файла не достигнут, или значение, отличное от 0, если при последней операции чтения из файла был достигнут конец файла.
int ferror(FILE * fp);
Макрос ferror() выполняет проверку, была ли ошибка ввода-вывода в файле fp, и возвращает 0, если ошибки не было, или значение, отличное от 0, если ошибка была. Если же следующая после ошибочной операция с файлом пройдет успешно, то функция возвратит 0 и сообщение об ошибке будет потеряно.
Функции потокового ввода-вывода можно разделить на 4 группы.
1. Функции посимвольного ввода-вывода – за одно обращение к файлу передаётся один символ.
2. Функции построчного ввода-вывода – за одно обращение передаётся строка.
3. Функции блочного ввода-вывода – за одно обращение передаётся блок информации (байтов), при работе с ними лучше открывать файлы в бинарном режиме.
4. Функции форматированного ввода-вывода – за одно обращение передаётся строка, формируемая по заданной строке формата, в которую могут быть подставлены значения переменных разных типов.
int getc(FILE * stream);
int putc(const int c, FILE * stream);
Макрос getc() производит ввод символа из потока stream. Макрос putc() производит вывод символа, код которого принимает в качестве аргумента c, в поток stream. Оба макроса в случае успеха возвращают код символа, в случае ошибки – EOF.
int fgetc(FILE * stream);
int fputc(int c, FILE * stream);
Функция fgetc() производит ввод символа из потока stream. Функция fputc() производит вывод символа, код которого принимает в качестве аргумента c, в поток stream. Обе функции в случае успеха возвращают код символа, в случае ошибки – EOF. Они аналогичны макросам getc() и putc().
char * fgets(char* s, int n, FILE * stream);
Функция fgets() производит ввод символов из потока stream в буфер, адрес которого принимает в качестве параметра s, пока не встретится символ перевода строки или пока не будет прочитано (n-1) символов. После последнего введенного символа функция помещает нулевой байт, либо преобразует символ перевода строки в нулевой байт. Функция в случае успеха возвращает s, в случае ошибки – NULL.
int fputs(const char * s, FILE * stream);
Функция fputs() производит вывод строки, адрес которой принимает в качестве параметра s, в поток stream. Функция в случае успеха возвращает неотрицательное значение, в случае ошибки – EOF.
size_t fread(void * ptr, size_t size, size_t n, FILE * stream);
size_t fwrite(const void * ptr, size_t size, size_t n, FILE * stream);
Функции fread() и fwrite() осуществляют чтение и запись соответственно блока данных в файл или из файла. Указатель ptr указывает на начало блока данных, n – число записей длиной size байтов, которые будут считаны или записаны, size – размер одной записи в байтах, stream – указатель на поток. В случае успеха функции возвращают число считанных или записанных записей, в случае ошибки – 0.
int fscanf(FILE * stream, const char * format, ...);
int fprintf(FILE * stream, const char * format, ...);
Функции fscanf() и fprintf() осуществляют форматированный ввод и вывод соответственно (аналогично функциям scanf() и printf()) в поток (из потока) stream.
int sscanf(const char * buffer, const char * format, ...);
int sprintf(char * buffer, const char * format, ...);
Функции sscanf() и sprintf() осуществляют форматированный ввод и вывод соответственно (аналогично функциям scanf() и printf()) в стороку (из строки) buffer.
В случае успеха функции fprintf() и sprintf() возвращают число выведенных символов, в случае ошибки – EOF. В случае успеха функции fscanf() и sscanf() возвращают число удачно введённых и распознанных полей, 0 – если ни одного поля не распознано, в случае ошибки – EOF.
Стандартные потоки.
При запуске программы системой создаются структуры типа FILE, связанные со стандартными потоками:
stdin – стандартный поток ввода (связан с клавиатурой);
stdout – стандартный поток вывода (связан с монитором);
stderr – стандартный поток ошибок (связан с монитором);
stdaux – стандартный поток дополнительного устройства (связан с портом COM1);
stdprn – стандартный поток принтера (связан с принтером).
Два последние потока являются дополнительными, данные устройства могут и не поддерживаться ОС или не входить в состав ПК.
Эти имена описаны в файле stdio.h в виде макросов, результатом макрорасширения и будет адрес структуры типа FILE. С помощью данных потоков осуществляется ввод-вывод на стандартные устройства компьютера.
При завершении работы программы данные потоки закрываются автоматически.
Предопределённые префиксы файлов стандартного ввода-вывода приведены в таблице ниже.
Префикс | Имя устройства | Имя потока |
00h | CON | stdin |
01h | CON | stdout |
02h | CON | stderr |
03h | AUX | stdaux |
04h | PRN | stdprn |
Функции для работы со стандартными потоками.
Для функций ввода окончание ввода осуществляется нажатием клавиши ENTER.
Функции printf() и scanf() были рассмотрены на практических занятиях ранее.
int getchar(void);
int putchar(const int c);
Макрос getchar() производит ввод символа из стандартного потока ввода. Макрос putchar() производит вывод символа, код которого принимает в качестве аргумента, в стандартный поток вывода. Оба макроса в случае успеха возвращают код символа, в случае ошибки – EOF.
char * gets(char * s);
Функция gets() производит ввод строки из стандартного потока ввода в буфер, адрес начала которого принимает в качестве параметра. Функция в случае успеха возвращает s, в случае ошибки – NULL.
int puts(const char * s);
Функция puts() производит вывод строки, адрес которой принимает в качестве параметра, в стандартный поток вывода. Функция в случае успеха возвращает последний записанный символ, в случае ошибки – EOF.
void perror(const char * s);
Функция выводит в стандартный поток ошибок stderr строку, адрес которой принимает в качестве параметра.
– Конец работы –
Эта тема принадлежит разделу:
На сайте allrefs.net читайте: Лекция 29-30.
Если Вам нужно дополнительный материал на эту тему, или Вы не нашли то, что искали, рекомендуем воспользоваться поиском по нашей базе работ: Лекция 29-30
Если этот материал оказался полезным ля Вас, Вы можете сохранить его на свою страничку в социальных сетях:
Твитнуть |
Новости и инфо для студентов