Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Технология программиования_Си.docx
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
33.09 Кб
Скачать

Дескрипторы файлов (потоков).

Когда программа загружается в память для выполнения, для неё создаётся таблица открытых файлов. Программа одновременно может работать с несколькими файлами, часть из них может использоваться для чтения, часть для записи. Каждому файлу соответствует свой поток. Каким образом библиотечные функции узнают, с каким из потоков они должны взаимодействовать? Для этого операционная система с каждым потоком связывает дескриптор (handle). Реально, дескриптор это номер потока. При загрузке программы автоматически создаётся несколько стандартных потоков (с дескрипторами от 0 до 4), поэтому потоки, открываемые программистом будут иметь большее значение дескрипторов (от 5 и дальше).

Библиотечные функции системного уровня требуют передачи им дескрипторов потока. При использовании библиотеки стандартного уровня, программист непосредственно с дескриптором не работает. Вместо этого функциям стандартного уровня передаётся структурная переменная типа FILE.

Библиотечный файл stdio.h

typedef struct {

unsigned flags;

char fd; /*file descriptor*/

unsigned char* buffer;

unsigned char* curp;

…}FILE;

Значит давайте запишем следующее, чтоооо

Я вам приводил дескриптор от 0 до 4 и есть структуры типа …….

Для стандартных потоков ввода-вывода в Си определяются стандартные имена для их структур типа файла.

Stdin – стандартный поток ввода (дескриптор 0), по умолчанию связан с клавиатурой.

Stdout – стандартный поток вывода, по умолчанию связан с дисплеем (дескриптор 1).

Stderr – стандартный поток вывода ошибок (дескриптор 2(наверн)).

Stdout может быть перенаправлен например в память, но если в программе произошла ошибка, то программист может не увидеть сообщение. Поэтому stderr отличается от stdout тем, что его нельзя перенаправить.

Stdaux – дополнительный поток для коммуникационных сетей

Stdprn – стандартный поток вывода на печать.

fprintf(FILE* fp, char* format,…)

printf -> fprintf(stdout,…)

fprintf(stderr, …)

Открытие и закрытие файлов

Для того чтобы начать работу с файлом, его нужно открыть. Процедура открытия предполагает выполнение большого количества действий:

  1. Получить от операционной системы ещё не занятый дескриптор потока.

  2. Выделить память для буфера

  3. Заполнить поля структуры типа файла

  4. И т.д…

Флаги описывают режим, в котором открывается поток. Например, если поток открывется только для чтения, то он не позволяет записывать данные. Кроме того, то режима открытия файла зависит, что происходит, когда файла нет. Если мы пытаемся записать несуществующий файл, то он должен быть создан, а если мы пытаемся прочесть из несуществующего файла, то должна возникнуть ошибка.

Для открытия потоков (файлов) используется функция fopen со следующим прототипом:

FILE*fopen(имя_файла, режим_открытия). Оба аргумента – строки.

При задании имени файла может быть указан путь. Нужно не забывать удваивать бэк-слеши.

«C:\\programs\\data\\mydata.txt»

Если пусть не указан, то файл ищется в той же папке, где находится программа. Строка режим открытия описывает особенности использования потоков. Поток может быт открыт для чтения, записи или дозаписи. Если файл не существует, то в режиме чтения будет ошибка, а в режиме записи или дозаписи будет создан новый файл. Есть менее ограничивающие режимы. «r+» - открыть существующий файл для чтения и записи, «w+» - создать новый файл для чтения и записи. В режимах w w+ , если файл уже существовал, то старое его содержимое будет затёрто и запись начнётся с начала файла. «a+» — дополнить или создать файл с возможностью чтения и записи. Кроме этого, можно указать, каким должен рассматриваться файл – бинарным или текстовым. Для этого используется символы-делители (b,t), которые дописываются к рассмотренным режимам («w+t», «wb»).

При открытии файла расходуются ресурсы ОС – память и дескрипторы файлов. Поэтому, когда работа с файлом завершена, поток нужно закрыть. Для этого используется функция:

int fclose(FILE*fp). При успешном завершении функция возвращает 0, при ошибке – не ноль.

Операция открытия файла является рискованной, так как при её выполнении могут возникать ошибки. Например программист неправильно указал имя файла, файл был перемещён в другую папку, и т.д. Поэтому каждый раз, когда открывается файл , прежде чем с ним работать, нужно убедиться, что процедура открытия завершилась успехом. В случае успеха fopen возвращает указатель на файл, а в случае неудачи – NULL.

FILE *fp;

fp = fopen(“my_file.txt”, “r”);

if (fp==NULL) {

puts(“Ошибка”);

exit(1);

}

Или if (fp=fopen(…)) {

}

Else {ошибка}

Функции ввода-вывода и библиотеки std уровня

Ввод-вывод символов: int putc(int c, FILE *fp)

В случае успеха функция возвращает код символа, а в случае неудаче — -1 (EOF)

Int getc(FILE *fp)

В случае успеха операции возвращается код считанного символа, при неудаче – аналогично putc.

getchar — getc(stdin)

Ввод-вывод строк:

char* fputs (char *str, FILE *fp)

Пример:

fputs(“Ошибка!”, stderr)

char* fgets(char* str, int n, FILE* fp)

n – количество символов, которые нужно прочесть.

fprintf(FILE* fp, форм строка, …)

fscanf(FILE *fp, форматная строка, …)

printf fprintf(stdout,…)

Управление произвольным доступом

При работе с текстовыми файлами возникает необходимость выполнить следующую операцию чтения или записи, начиная с определённой позиции в файле. В каждом файловом потоке есть внутренний указатель. Библиотека ввода-вывода предлагает ряд функций для работы с этим указателем. В обычном режиме чтение и запись ведутся последовательно, а при управлении внутренним указателем мы можем обеспечить произвольный доступ к фалу. Для управления позиционированием используется функция

int fseek( FILE *fp, long count, int access)

Для того, чтобы указать, куда нужно поместить внутренний указатель потока, используется два параметра. Параметр access определяет точку отсчёта. Он принимает три значения, для которых определены именованные константы:

SEEK_SET 0 SEEK_CUR 1 SEEK_END 2

SEEK_SET означает, что новая позиция будет отсчитываться от начала файла, SEEK_CUR – от текущей позиции, SEEK_END – от конца. Параметр count задаёт смещение относительно точки отсчёта. В случае SEEK_SET он должен быть положительным, в случае SEEK_END – отрицательным, а в случае SEEK_CUR – и положительным и отрицательным. При успешном завершении операции функция возвращает 0, при неудаче не 0.

Чтобы получить текущую позицию внутреннего указателя потока, используется функция

long ftell(FILE *fp)

Есть возможность перенести текущую позицию в начало файла

void rewind(FILE *fp)