Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Иванова Г.С. - Основы программирования

.pdf
Скачиваний:
2771
Добавлен:
02.04.2015
Размер:
13.53 Mб
Скачать

 

6. Файловая система. Файлы

 

else

 

 

 

begin

 

 

 

ReadLn(fl,st);

{читаем строку}

 

WriteLn(f2,st); {записываем ее в новый файл}

end;

 

 

 

end;

 

 

 

Close(fl);

{закрываем старый файл}

 

Close(f2);

{закрываем новый файл}

 

Erase(fl);

{удаляем старый файл}

 

ReName(f2,name);

{переименовываем новый файл}

end

 

 

 

else WnteLn('0au/i с таким именем не найден.

*);

End

Задания для самопроверки

Задание 1. Дан текстовый файл, состоящий из символьных строк, представля­ ющих собой совокупность слов, разделенных пробелами. Разработайте программу, которая переформирует файл, заменяя в каждой строке сочетание «это» на сочетание «то», и удаляя слова, начинающиеся с символа #. Вывести на экран скорректирован­ ный файл.

Задание 2. Разработайте программу, которая осуществляет поиск в текстовом файле заданных слов. Слова последовательно вводятся с клавиатуры. Для каждого слова должно определяться количество вхождений и номера строк текста. Если ука­ занные слова в файле отсутствуют, то программа должна выводить соответствующее сообщение.

6.4. Типизированные файлы

Типизированный файл - это файл, все компоненты которого одного типа, заданного при объявлении файловой переменной (рис. 6.5). Компоненты файла хранятся на диске во внутреннем (двоичном) формате и нумеруются с 0. Если посмотреть такой файл любым текстовым редактором, то можно рас­ познать только символьную информацию, на месте же чисел в файле будут располагаться пробелы или символы псевдографики.

Указатель файла

Маркер конца файла

Компоненте Компонент 1 Компонент 2

Компонент 3 Компонент 4

Рис. 6.5. Типизированный файл

201

Часть 1. Основы алгоритмизации и процедурное программировани

Для работы с типизированными файлами используют специальные про­ цедуры и функции.

1. Процедура Read(Var /; с1, с2, ...,сп) - осуществляет чтение очередных компонентов типизированного файла. Список переменных ввода содержит одну или несколько переменных того же типа, что и компоненты файла, раз­ деленных запятыми. Если файл исчерпан, обращение к процедуре вызывает ошибку ввода-вывода.

2.Процедура Write(Var f; cly с2у ...уСп) - осуществляет запись данных в типизированный файл. Список вывода содержит одно или более выражений того же типа, что и компоненты файла, разделенных запятыми.

3.Процедура Seek(Var f; numcomp:word) ~ осуществляет установку указателя файла на компонент файла с номером numcomp.

4.Функция FileSize(Var f):longint - возвращает количество компонент файла, указанного файловой переменной. Может использоваться для уста­ новки на конец файла совместно с Seek():

Seek(f, РПе512еф);,.,

5. Функция FilePos(Var fi.iongint- возвращает порядковый номер ком­ понента, который будет обрабатываться следующей операцией ввода-выво­ да.

После открытия файла для чтения или записи указатель файла стоит в его начале и указывает на первый компонент, имеющий номер 0. После каж­ дого чтения или записи указатель сдвигается к следующему компоненту фай­ ла. Поскольку длина каждой компоненты файла строго постоянна, помимо последовательного возможно осуществление прямого доступа к компонен­ там файла. По той же причине, если требуется изменить компонент файла, то не обязательно переписывать компоненты в другой файл, а достаточно уста­ новить указатель файла на изменяемый компонент и записать новый компо­ нент на место старого.

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

Добавление компонентов в середину или начало файла может выпол­ няться следующим образом: определяем место, в которое должны быть до­ бавлены элементы, все последующие компоненты переписываем во времен­ ный файл, вставляем новые компоненты и, наконец, дописываем в файл ком­ поненты, переписанные во временный файл.

Удаление компонент обычно требует перезаписи файла.

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

202

 

6. Файловая система. Файлы

Program ex;

 

Varfyflifile of char;

{ две файловые переменные}

chyVchar;

 

j:longint;

 

name:strmg[8];

 

Begin

 

WriteLnCВведите имя файла: *); ReadLn(name);

{создание и открытие файла}

Asslgn(f, name-^\dat^); {связываем файл с файловой переменной}

ReWrite(f);

{открываем файл для записи (создаем)}

WriteLnCВводите символы или CTRL-Z:');

{занесение записей в файл}

while not EOF do {пока не введено CTRL-Z с клавиатуры} begin

ReadLn(ch); {вводим символ с клавиатуры} Write(fyCh); {записываем символ в файл}

end;

WriteLn;

{последовательное чтение записей из файла}

ReSet(P;

 

{открываем файл для чтения}

while not EOF(/) do

{пока не достигнут конец файла}

begin

 

 

 

Read(f,ch);

 

{читаем символ из файла}

Write(cK ' ');

{выводим символ на экран}

end;

 

 

 

WriteLn;

 

 

 

{изменение записей в файле}

ReSet(f);

 

 

{открываем файл для чтения}

while not EOF(f) do

{пока не достигнут конец файла}

begin

 

 

 

Read(f,i);

 

 

{читаем символ из файла}

Write(i,'

');

 

{выводим символ на экран}

i:=chr(ord(i)+10);

{изменяем символ}

WriteLn(i);

 

{выводим на экран измененный символ}

Seek(fyFUePos(f)'l);

{возвращаемся на один компонент}

Write(fyi);

 

{перезаписываем символ}

end;

 

 

 

WriteLn;

 

 

 

{попеременное чтение записей с начала и конца файла}

ReSet(f);

{открываем файл для чтения}

/•=0;

{устанавливаем номер компонента равным 0}

while not EOF(f) do

{пока не достигнут конец файла}

begin

 

 

 

203

Часть I, Основы алгоритмизации и процедурное программирование

Read(fJ); {читаем символ из начала файла}

Write(i);

{выводим символ на экран}

Seek(fyFileSize(f)-FilePos(f)); {устанавливаем указатель

Read(fyi);

 

для чтения из конца файла}

{читаем символ из конца файла}

Wnte(i);

{выводим символ на экран}

j:=j+l:

{увеличиваем номер компонента}

Seek(fJ);

{устанавливаем указатель на следующий от

end;

 

начала компонент}

 

 

WriteLn;

 

 

WriteLnCВведите символ для удаления: *); ReadLn(ch);

{подготовка к удалению записей: переименование исходного

файла и открытие нового файла с тем же именем}

Close(f);

 

{закрываем файл}

ReName(fyname-^\bak^); {переименовываем файл}

ReSet(f);

 

{открываем файл для чтения}

Assign(fl,name+\dat');

{связываем новый файл с переменной}

ReWrite(fl);

 

{открываем новый файл для записи}

{удаление записей - перепись остающихся записей в другой файл}

while not EOF(f) do

 

begin

 

Read(fyi);

{читаем символ из файла}

ifioch then Write(fJ,i); {если символ не подлежит удалению, то записываем его в новый файл}

end;

Erase(f); {удаляем старый файл, после закрытия в нем ничего не изменилось, поэтому повторно его можно не закрывать}

{последовательное чтение записей из нового файла}

ReSet(fl); {открываем новый файл для чтения} while not EOF(fl) do

begin

Read(flyCh); {читаем из файла}

Write(ch ' '); end;

WriteLn;

End

Пример 6.4. Разработать программу, которая создает файл, содержащий список фамилий и даты рождения. Осуществить поиск в этом файле даты рождения по заданной фамилии.

204

Write(fjb);
end;
Close(f);

 

6. Файловая система. Файлы

Program ex;

 

 

 

Typefam=record

{тип запись «сведения о сотрудниках»}

ff:string[20];

{фамилия}

year:word;

{год рождения}

month:L.12;

{месяц рождения}

day:L,31

 

{день рождения}

end;

 

 

 

Varf:file offam;

{файловая переменная «файл сотрудников»}

jbifam:

 

 

 

пJ: integer;

 

 

 

fffistring;

 

 

 

key;boolean;

 

 

 

Begin

 

 

 

Assign(f,'(udat');

{связываем файловую переменную с файлом}

ReWrite(J);

 

{открываем файл для записи}

WriteLnCВведите

данные или CTRL-Z);

while not EOF do

{цикл, пока не введено CTRL-Z}

begin

ReadLn(/b.ff, fb.year, fb.month, fb.day); {вводим данные по полям,

фамилию вводим в отдельной строке, так как ввод строки завершается нажатием клавиши Enter} {заносим запись в файл как один компонент}

{закрываем файл}

WriteLnCВведите фамилию'); Readln(ffJ);

key;=false; {устанавливаем признак «запись не найдена»} ReSet(f); {открываем файл для чтения}

while (not EOF(f)) and (not key) do {пока не обнаружен конец файла и не найдена запись}

begin

Read(fjb); {читаем запись из файла} iffbjf^fffthen {если фамилии совпадают, то} begin {выводим данные}

WriteLnCJlama: \fb.year,fb. month;3,fb. day;3);

key;=true;

{устанавливаем признак «запись найдена»}

end;

 

end;

 

if not key then

{если признак не установлен}

WriteLn('Hem данных ) ; {то выводим «нет данных»} Close(f); {закрываем файл}

end,

205

Часть I. Основы алгоритмизации и процедурное программирование

Следует отметить, что любой текстовый файл может быть прочитан как типизированный файл с компонентами типа CHAR. В этом случае необходи­ мо учитывать, что маркер конца строки текстового файла рассматривается в символьном представлении как последовательность из двух символов #13 и #10.

Пример 6.5. Разработать программу, которая открывает текстовый файл как типизированный с компонентом типа CHAR и читает его по символу.

Program charjextjile;

Type ff=file of char; {новый тип - символьный файл}

Var

Л/Л {файловая переменная типа файл символов} a:char;

n,i: integer; Jhame,st:string[30];

Begin

WriteLn('Beedume имя файла'); ReadLn(fname); Assign(ffname); {связываем файловую переменную с файлом}

ReSet(f); {открыть текстовый файл как типизированный на чтение} while not EOF(f) do {пока не достигнут конец файла}

begin

St-'';

Read(f^a); {читаем символ}

while (ао#13) and not EOF(f) do {до маркера конца строки или конца файла}

begin

st:='st+a; {добавляем считанный символ в строку} Read(f,a); {читаем очередной символ}

end;

if not EOF(f) then Read(f,a); {пропускаем символ #10}

WriteLn(st); {выводим сформированную строку} end;

Closeif); End

Задания для самопроверки

Задание 1. Разработайте программу, которая создает типизированный файл, со­ держащий сведения об импортируемых в Россию товарах: наименование товара, страна, поставляющая товар, и объем поставляемой партии. В сформированном фай­ ле определить товары, импортируемые из страны Р (вводимой с клавиатуры в про­ цессе выполнения профаммы), а также объем партий. Если импорт из страны отсут­ ствует, вывести соответствующее сообщение.

206

6, Файловая система. Файлы

Задание 2. Разработайте профамму, которая формирует типизированный файл из К целых чисел в диапазоне -50 +120, используя датчик случайных чисел как для задания К (К находится в диапазоне от 1 до 100), так и для задания значений компо­ нент файла. Для сформированного файла определите сумму его четных отрицатель­ ных компонент и поместите эту сумму вместо максимального по абсолютной вели­ чине компонента этого же файла.

Задание 3. Дан типизированный файл вещественных чисел. Разработайте про­ грамму, которая определяет среднее арифметическое значение компонент файла. Удалите из файла все компоненты, меньшие найденного среднего арифметического. Выведите на экран исходный и переформированный файлы и значение среднего арифметического.

6.5. Нетипизированные файлы

Нетипизированными называют файлы, объявленные без указания типа его компонентов. Операции чтения и записи с такими файлами осуществля­ ются блоками. Отсутствие типа компонента делает эти файлы совместимы­ ми с любыми другими, а выполнение ввода/вывода блоками позволяет орга­ низовать высокоскоростной обмен данными между диском и памятью. Нети­ пизированные файлы, как и типизированные, допускают организацию пря­ мого доступа.

Нетипизированный файл можно открыть для записи и чтения, используя процедуры ReSet и ReWrite. При открытии нетипизированного файла этими процедурами вторым параметром recsize можно указать длину записи файла в байтах. Если длина записи не указана, она принимается равной 128 байтам:

ReSet (Var f; [recsize:word\);

ReWrite(Var f; [recsize:word ] /

Длина записи recsize - положительное число, не превышающее 65535 байт. Для обеспечения максимальной скорости обмена данными следует за­ давать длину, которая была бы кратна размеру сектора диска (512 байт), на­ пример: 1024,2048.

При работе с нетипизированными файлами можно использовать все процедуры и функции, предназначенные для работы с типизированными файлами, за исключением процедур Read и Write. Эти процедуры заменяют­ ся высокоскоростными процедурами BlockRead и BlockWrite.

1. Процедура BlockRead(Var f:file;Var buf; CounCword [;res:word] ) -

осуществляет чтение блока записей из файла в буфер.

Параметр buf определяет буфер, который будет участвовать в обмене данными. Размер буфера должен быть достаточен для размещения Count за­ писей указанной в процедуре ReSet длины.

207

Часть L Основы алгоритмизации и процедурное программирование

Параметр res будет содержать количество фактически обработанных за­ писей. Если последняя запись - неполная, т.е. ее длина меньше указанной длины записи, то значение параметра res не будет ее включать,

2, Процедура BlockWrite(Var fifile; Var buf; Count:word [;res:word\) - осуществляет запись блока из буфера buf в файл.

Пример 6.6, Разработать программу копирования файлов. При создании данной программы нам безразлично, что именно хранится в файле, поэтому используем нетипизированные файлы. При этом длину записи установим равной 1, буфер предусмотрим на 2048 байт. Так мы гарантируем отсутствие неполных записей и в то же время за одну операцию будем обрабатывать

блок большого размера.

 

Program copir;

 

Const recs=1024; {размер записи}

 

Var y7,yi7.y/fe;{нетипизированные

файлы}

buf: array [L.2*recs] of byte;

{буфер на 2048 байт}

i:word;

 

namein,nameout: string;

 

Begin

 

WriteLnCВведите имя файла -

источника:');

ReadLn(namein);

 

{проверка наличия файла с указанным именем}

Assign(fiynamein);

{$Ч

 

ReSet(fiyl);

{открываем файл для чтения}

{$!+}

 

iflOResulto

О then

begin

 

WriteLn(#7,' Не существует файла с именем \namein); Halt

end;

WriteLnСВведите имя файла - приемника '); ReadLn(nameout);

Assign(fo,nameout);

ReWrite(fOyl); {открываем файл для записи} while not EOF(fi) do

begin

BlockRead(ft,buf,sizeof(buf),i);{читаем блок из входного файла}

BlockWrite(fo,bufi);{пишем блок из буфера в выходной файл} end;

Close(fi);

Close(fo)

End

208

6.Файловая система. Файлы

6.6.Процедуры и функции библиотеки DOS для работы с файлами

Borland Pascal предоставляет программисту возможность обращения к некоторым функциям MS DOS, обеспечивающим функционирование файло­ вой системы. Для этого необходимо в начале программы подключить библи­ отеку Dos с помощью директивы Uses Dos, чтобы сделать доступными ее ре­ сурсы, описанные в этом разделе.

Для работы с файлами библиотека Dos содержит следующие процедуры и функции.

1. Функция DiskFree((lrive:byte):LongInt-опродоляет и возвращает объ­ ем свободного места на диске drive в байтах. Параметр drive может прини­ мать значения: О - устройство по умолчанию, 1 - диск А, 2 - диск В и т.д.

2.Функция DiskSize(drive:byte):LongInt - возвращает полный объем указанного диска в байтах. Параметр drive принимает те же значения, как и

впредыдущей функции.

3.Процедура GetFTime(Varf; Var time:LongInt) - возвращает время со­ здания или последнего обновления указанного файла f. Время возвращается

вупакованном формате, который необходимо распаковать.

4.Процедура UnPackTime (time:LongInt; Var DT:DateTime) - распако­ вывает значение параметра time, который содержит время в упакованном формате, в специальный тип DateTime, описанный в модуле Dos следующим образом:

Туре DateTime = record

 

year:

word;

{год}

month:

word;

{месяц: 1..12}

day:

word;

{число: 1..31}

hair:

word;

{часы: 0..23}

min:

word;

{минуты: 0..59}

sec:

word;

{секунды: 0..59}

 

end;

 

5.Процедура PackTime(DT:DateTime;Var time:LongInt) - позволяет упаковать параметр DT типа DateTime в целое число time.

6.Процедура SetFTime(Varf; time:LongInt) - используется для установ­ ки даты создания или обновления файла; time - время и дата в упакованном формате.

7.Процедура GetFAttr (Varf; Var Attnword) - применяется для получе­ ния атрибутов файла, указанного файловой переменной. Атрибуты файла («только чтение», «скрытый», «системный» и т.д.) кодируются битами байта атрибутов файла. Комбинация битов в байте может указывать самые разные варианты. Байт атрибутов возвращается в младшем байте параметра Attr.

209

Часть 1. Основы алгоритмизации и процедурное программирование

Для расшифровки байта атрибутов в модуле Dos описаны специальные мас­ ки длиной 1 байт:

Const

Readonly

= $01:

{только чтение}

 

Hidden

= $02;

{скрытый файл}

 

Sysfile

= $04;

{системный файл}

 

VolumelD

= $08;

{идентификатор тома}

 

Directory

= $10;

{имя подкаталога}

 

Archive

= $20;

{архивный файл}

 

Anyfile

= $3F;

{любой файл}

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

GetFAttr(fMrF);

if Lo(AttrF) && Readonly oO then

WriteLn('0am имеет атрибут ''только чтение'**);

8.Процедура SetFAttr(Varf; Attr:word) - служит для установки атрибу­ тов файла указанного файловой переменной.

9.Функция FSearch(path:PathStr; DirList:s(rlng):PathStr - возвращает путь к файлу, заданному в строке path, который ищется в указанном списке каталогов; имена каталогов в списке должны быть разделены точкой с запя­ той «;». Если файл не найден, то возвращается пустая строка.

\0. Процедура FSpllt(patlt:PathStr; Var DinDlrStr; Var name:NameStr; Var Ext:ExtStr) - осуществляет расщепления имени файла, заданного в path,

т.е. возвращает в качестве отдельных строк путь к файлу dir, его имя name и расширение ext. Процедура не проверяет наличие на диске указанного фай­ ла.

11.Функция FExpand(path:PathSrt):PathStr - возвращает полное имя указанного файла. Функция не проверяет наличие файла на диске, а просто дополняет имя файла недостающими параметрами.

Пример 6.7. Разработать программу, которая обращается к функциям

библиотеки Dos для:

 

 

определения и изменения даты создания файла;

определения атрибутов файла;

 

определения количества свободного места на диске.

Programfundos;

{ проверка функций библиотеки dos}

 

Uses dos,crt;

 

 

 

VarfiJo:text;

{текстовые файлы}

 

 

к, i:word;

tinte,size:longint;

date:DateTime;

 

patltf:DirStr;

namef:NameStr;

extfiExtStr;

atribyte; {переменные для хранения байта атрибутов файла} name:string;

210