Иванова Г.С. - Основы программирования
.pdf
|
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
|
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