Автор: Пользователь скрыл имя, 28 Декабря 2011 в 12:54, реферат
Надо заметить, что физически единой эта область данных вовсе не является: файл обычно состоит из целого набора так называемых кластеров (участков диска фиксированного для операционной системы размера), которые разбросаны по диску тем прихотливее, чем чаще мы стираем и записываем на него информацию.
Вообще, система окажется наиболее производительной, если кластеры файла будут идти не подряд, а с неким постоянным интервалом: пока система "переварит" данные с одного кластера, диск как раз успеет повернуться до другого.
4. Прямой доступ к файлу данных
Мы уже говорили, что самый естественный доступ к файлу - последовательный, он лучше всего соответствует линейной структуре файла. Если задача требует прямого доступа к компонентам файла, мы можем запрограммировать такой доступ "в лоб" или воспользоваться стандартными процедурами и функциями Паскаля.
Например, пусть файл F - типизированный:
Reset(F); {сейчас мы можем считать 1-й компонент файла} for i:=1 to 20 do Read (F, v); {в переменной v значение 20-го компонента файла} Reset(F); {а сейчас мы снова готовы читать 1-й компонент} |
Процедуры и
функции прямого доступа
Функция FileSize(var F) : LongInt возвращает число записей в открытом файле F. Записями будут считаться компоненты типизированного файла или блоки размером с буфер бестипового. Причем для нетипизированного файла функция возвращает число полных блоков: оставшийся неполный "хвост" не учитывается.
Функция FilePos(var F) : LongInt возвращает номер последнего считанного компонента или блока. Для начала файла функция вернет 0, для состояния конца файла - номер последнего компонента (блока).
Процедура Seek(var F; N: LongInt) устанавливает файловый курсор на компонент или блок с номером N, считая нулевым блоком начало файла. N-й компонент будет считан или записан следующей операцией ввода-вывода. Файл при этом должен быть открыт.
Для демонстрации
прямого доступа давайте
const FILENAME = 'example.dat'; var F: File of char; ch: char; i: integer; begin writeln('Работаем с файлом "example.dat"'); Assign(F, FILENAME); Rewrite(F); writeln('Текущий размер файла = ', FileSize(F)); writeln('Текущая позиция в файле = ', FilePos(F)); for i:=1 to 20 do begin ch:=chr(ord('0')+random(10)); Write(F,ch); end; writeln('Теперь размер файла - ', FileSize(F)); writeln('И текущая позиция в нем - ', FilePos(F)); Seek(F, FileSize(F) div 2); writeln('Теперь текущая позиция = ', FilePos(F)); ch:='У'; Write(F,ch); ch:='Р'; Write(F,ch); ch:='А'; Write(F,ch); end. |
Вывод на экран при выполнении этой программы будет следующим:
Работаем с файлом "example.dat" Текущий размер файла = 0 Текущая позиция в файле = 0 Теперь размер файла - 20 И текущая позиция в нем - 20 Теперь текущая позиция = 10 |
А в файл будет записана информация вроде этой (цифры могут меняться, но положение "УРА" в файле останется таким же):
0082263134УРА8029373 |
Надо сказать, что в очень редких задачах мы заранее знаем позицию нужного нам компонента в файле данных. Обычно, чтобы обработать нужную нам информацию, мы ищем необходимые записи простым линейным поиском - перебирая все элементы файла по очереди.
Например: пусть в файле данных записаны сведения о книгах: жанр, автор, название, издательство, год издания. Необходимо подсчитать количество книг заданного автора.
Библиотеку можно заполнять и вручную, но это долго и неудобно. Давайте вначале создадим модуль создания файла "базы данных" библиотеки, для которого книги будут генерироваться случайным образом из заданных списков значений.
program CreateLibrary; (***************************** * Для задач об имитации базы данных "Библиотека" при * * помощи типизированного файла. Создание библиотеки * * из случайно генерируемых книг. * ****************************** const {константы для жанров} KINDSNUM = 6; KINDMAX = 10; CKinds : array [1..KINDSNUM] of string[KINDMAX] = ('Проза','Учебная','Детская',' {константы для авторов} AUTHORSNUM = 17; AUTHORMAX = 15; CAuthors : array [1..AUTHORSNUM] of string[AUTHORMAX] = ('А.С.Пушкин','Н.В.Гоголь','Ф. 'А.П.Чехов','Ф.Купер','А.Дюма' 'Т.Сван','Б.Страуструп','У. {константы для названий} NAMESNUM = 34; NAMEMAX = 40; CNames : array [1..NAMESNUM] of string[NAMEMAX] = ('Руслан и Людмила','Сказка о рыбаке и рыбке','Мертвые души', 'Вечера на хуторе близ Диканьки','Преступление и наказание', 'Братья Карамазовы','Идиот','Царь- 'Лошадиная фамилия','Зверобой','Следопыт' 'Императоры иллюзий','Фальшивые
зеркала','Спектр','Выбраковка' 'К-10','Рыцари кувалды','Миссионеры',' 'Программирование в Borland Builder C++','Язык С++ для профессионалов', 'Джонни-мнемоник','Нейромант', 'Лавина','Алмазный век','Белый свет','Приключения Незнайки', 'Веселая семейка','Мишкина
каша'); {константы для издательств} PUBLICSNUM = 9; PUBLICMAX = 15; CPublics : array [1..PUBLICSNUM] of string[PUBLICMAX] = ('АСТ','Дрофа','Амфора',' 'Эксмо','Медицина');
type TBook = record Kind: string[KINDMAX]; Author: string[AUTHORMAX]; Name: string[NAMEMAX]; Public: string[PUBLICMAX]; Year: word; end; var Library: File of TBook; FileName: string; book: TBook; num, tmp, minyear, maxyear, i: word; ask: char; begin {вводим диапазоны} write('Введите количество книг в библиотеке: '); readln(num); write('Введите минимальный год издания: '); readln(minyear); write('Введите максимальный год издания: '); readln(maxyear); {минимум должен быть меньше максимума} if minyear>maxyear then begin tmp:=minyear; minyear:=maxyear; maxyear:=tmp; end; write('Введите имя файла библиотеки: '); readln(FileName); Assign(Library, FileName); Rewrite(Library); for i:=1 to num do begin {генерируем книгу из случайных полей} tmp:=random(KINDSNUM)+1; book.Kind := CKinds[tmp]; tmp:=random(AUTHORSNUM)+1; book.Author := CAuthors[tmp]; tmp:=random(NAMESNUM)+1; book.Name := CNames[tmp]; tmp:=random(PUBLICSNUM)+1; book.Public := CPublics[tmp]; book.Year
:= random(maxyear-minyear)+ {записываем получившуюся книгу в файл} Write(Library, book); end; Close(Library); writeln('Библиотека создана'); write('Хотите ли вы просмотреть получившуюся библиотеку? (д/н)'); readln(ask); if (ask='y')or(ask='Y')or(ask='д' Reset(Library); writeln; writeln('КАТАЛОГ БИБЛИОТЕКИ'); while not EOF(Library) do begin read(Library, book);
writeln(book.Kind:KINDMAX,'|',
book.Name:NAMEMAX,'|',book.Pub book.Year:4); end; end; end. |
Теперь сама программа подсчета:
program Library1;
(*****************************
* Задача: в файле данных записаны сведения о книгах: *
* жанр, автор, название, издательство, год издания. *
* Необходимо подсчитать количество книг заданного *
* автора.
******************************
const
{Максимальные размерности полей}
KINDMAX = 10;
AUTHORMAX = 15;
NAMEMAX = 40;
PUBLICMAX = 15;
type
TBook = record
Kind: string[KINDMAX];
Author: string[AUTHORMAX];
Name: string[NAMEMAX];
Public: string[PUBLICMAX];
Year: word;
end;
var
Library: File of TBook;
FileName: string;
author: string[AUTHORMAX];
book: TBook;
num, ErrCode: word;
begin
{открываем библиотеку}
repeat
write('Введите имя файла библиотеки: '); readln(FileName);
Assign(Library, FileName);
{$I-}
Reset(Library);
{$I+}
ErrCode:=IOResult;
if ErrCode<>0 then
writeln('Ошибка: невозможно открыть файл. Повторите ввод.');
until ErrCode=0;
write('Введите имя автора: '); readln(author);
{подсчитываем книги этого автора}
num:=0;
while not EOF(Library) do begin
Read(Library, book);
if book.Author=author then
num:=num+1;
end;
Close(Library);
writeln('Количество книг автора ',author,' в библиотеке = ',num,' шт.');
end.