Способы обработки файлов последовательного и прямого доступа

Смысл последовательного доступазаключается в том, что в каждый момент времени доступна лишь одна компонента из всей последовательности. Для того, чтобы обратиться (получить доступ) к компоненте с номером К, необходимо просмотреть от начала файла К-1 предшествующую компоненту. После обращения к компоненте с номером К можно обращаться к компоненте с номером К+1. Отсюда следует, что процессы формирования (записи) компонент файла и просмотра (чтения) не могут произвольно чередоваться. Таким образом, файл вначале строится при помощи последовательного добавления компонент в конец, а затем может последовательно просматриваться от начала до конца.

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

Прямой доступпредполагает, что файл представляет собой линейную последовательность блоков. Если файл содержит n блоков, то они нумеруются от 1 через 1 до n. Кроме того, вводится понятие условной границы между блоками, при этом условная граница с номером 0 расположена перед блоком с номером 1, граница с номером 1 расположена перед блоком с номером 2 и, наконец, условная граница с номером n находится после блока с номером n.

Реализация прямого доступа осуществляется с помощью функций и процедур FileSize, FilePos, Seek и Truncate.

------------------------------------------------------------------------------

Функция FileSize (var f): Longintвозвращает количество блоков в открытом файле f.

Функция FilePos (var f): Longintвозвращает текущую позицию в файле f. Позиция в файле – это номер условной границы. Для только что открытого файла текущей позицией будет граница с номером 0. Это значит, что можно записать или прочесть блок с номером 1. После чтения или записи первого блока текущая позиция переместится на границу с номером 1, и можно будет обращаться к блоку с номером 2. После прочтения последней записи значение FilePos равно значению FileSize.

Процедура Seek (var f; N: Longint)обеспечивает назначение текущей позиции в файле (позиционирование). В параметре N должен быть задан номер условной границы, предшествующей блоку, к которому будет производиться последующее обращение. Например, чтобы работать с блоком 4, необходимо задать значение N, равное 3. Процедура Seek работает с открытыми файлами.

Процедура Truncate (var f)устанавливает в текущей позиции признак конца файла и удаляет (стирает) все последующие блоки.

В тех случаях, когда программа обрабатывает достаточно большой объем данных, последние обычно организуются и хранятся вне оперативной памяти ЭВМ. Наиболее эффективным устройством для организации внешнего хранения данных являются диски. Прежде чем читать или записывать информацию в файл, надо открыть его с помощью стандартной библиотечной функции fopen.Программа, использующая эту функцию, должна включать во время компиляции системный файл stdio.h,в котором определен новый тип данных - FILE.

В программе нужно описывать ссылки на файлы и выглядит это, например, так: FILE *fu;

Здесь fuозначает указатель на FILE, а fopenвыдает ссылку на этот файл. Функция fopenимеет следующий заголовок:

FILE *fopen(char *fname, char type);

Обращение к fopenв программе делается так: fu=fopen(fname, type);

Строка символов fnameсодержит имя файла, который надо открыть;

type- тоже строка символов, заключенная в кавычки и указывающая, как будет использоваться файл: "r"-чтение, "w" - запись, "r+" - чтение с дозаписью, "a" -дозапись. Функция fopenвозвращает указатель, с помощью которого мы в дальнейшем будем обращаться к этому файлу.

Примеры:

FILE *uin, *uout;
uin=fopen("MAK1","r");
uout=fopen("MAK2","w");

Файл с именем MAK1открывается для чтения и далее идентифицируется как uin;

файл MAK2открывается для записи и связывается с идентификатором uout.

------------------------------------------------------------------------------

Язык (Турбо) СИ не содержит средств поддержки ввода/вывода. Каждая реализация СИ должна со-

провождаться библиотечными и макро, обслуживающими ввод/вывод. По мере развития СИ функции

ввода/вывода становились стандартизированными. Такая стандартизация обеспечила высокий уровень

мобильности программы на СИ.

Термин поток происходит из представления о последовательной структуре информационных запи-

сей [3]. Состав потока задается структурой FILE, описание которой задается в файле stdio.h.

Символ EOF определяется следующим образом:

#define EOF(-1)

Этот символ в операциях ввода/вывода служит для обозначения и проверки конца файла.

Функция fopen используется для открытия потока (файла). Интерфейс с функцией fopen описывает-

ся следующим образом:

FILE fopen(char filename, char type);

В качестве первого параметра функции должно передаваться правильное имя файла.

Второй параметр определяет тип открываемого файла.

Допустимы следующие типы файлов:

"r" Открыть уже существующий файл на ввод

"w" Создать новый файл или очистить уже существующий файл и

открыть его на вывод.

"a" Создать новый файл для вывода или осуществить вывод в конец уже существующего файла.

"r+" Открыть существующий файл для обновления, которое будет проводиться с начала файла.

"w+" Создать новый или открыть существующий файл для обновления его содержимого.

"a+" Создать новый файл или подстроиться в конец существующего файла для обновления его содер-

жимого.

Функция flclose выглядит следующим образом:

int fclose (FILE *stream);

С помощью этой функции файл закрывается.

Функция fseek описывается следующим образом:

int fseek (FILE *stream, long offset, int wherefrom);

Эта функция служит для произвольного доступа к байтам, обычно внутри двоичных потоков.

Первый аргумент задает поток, к которому должен осуществляться прямой доступ.

Второй аргумент указывает число байт смещения от точки, определяемой третьим параметром

функции.

Третий параметр указывает точку, от которой следует начинать отсчет смещения, заданного вто-

рым аргументом.

Значение 0 – смещение от начала файла.

Значение 1 – смещение от текущей позиции файла.

Значение 2 – смещение от конца файла.

5. ДИНАМИЧЕСКИЕ СТРУКТУРЫ

К динамическим структурам относят структуры, которые могут изменять свой размер.

Для организации таких структур используются динамические переменные, которые создаются и уничтожаются в процессе выполнения программы.

Характеризуются:

1. Эти переменные явным образом не описываются, к ним невозможно обратиться с помощью идентификатора.

2. Память для этих переменных не выделяется во время формирования кода программы. Она выделяется в специальной области оперативной памяти - heap-области - только во время выполнения программы.

3. Доступ к таким переменным выполняется с помощью указателей, которые становятся активными после определения динамического объекта и содержат адрес в виде <сегмент>:<смещение>

Структуры:

1. Массивы указателей

2. Линейные и циклические односвязанные списки, стек, очередь

3. Линейные двухсвязные списки

4. Деревья

Массив указателейна данные одного типа. Элементами такого массива есть указатели на базовую структуру: строка, запись, и т.п.. Хотя сам массив имеет фиксированный размер и занимает постоянное место в оперативной памяти, динамические элементы базового типа будут образовываться и размещаться в динамической памяти во время выполнения программы.

Линейный и циклический односвязанный список. Каждый отдельный элемент такой структуры содержит кроме одного или нескольких информационных полей поле, в котором сохраняется адрес следующего элемента. Последний элемент линейного списка содержит пустую ссылку (nil), тогда как последний элемент циклического списка содержит ссылку на первый элемент. Такие структуры образовываются и изменяются только во время работы программы.

Стек. С помощью линейного односвязного списка может быть построенный следующим образом: список будет возрастать из конца, от элемента с пустой ссылкой на следующий. Каждый очередной элемент будет прибавляться перед ним и становиться текущим (доступным для обработки - чтения). При чтении последнего элемента он уничтожается и указатель текущего элемента устанавливается на предыдущий.

Очередь. Также может быть построена с помощью линейного односвязного списка. Добавление элемента к очереди будет выполняться в конец списка (после последнего элемента), а считывание - из первого элемента со следующим его уничтожением. Таким образом надо будет сохранить два указатели - ссылка на первый и последний элементы очереди.

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

Двоичные деревья могут также быть построены на базе элементов с двумя адресными полями. Одно из них содержит ссылку на левую, а второе - на правую ветвь поддерева, которое начинается с данного узла. Если одна из ветвей отсутствующая, в адресном поле, предназначенном для нее, содержится nil.

Наши рекомендации