Тема 8. Файлы
Содержание 1. 2. 3. 4. 5. Общие сведения о файлах и файловой системе Файлы языка Паскаль Текстовые файлы Типизированные файлы Примеры решения задач обработки файлов 2
3 1. Общие сведения о файлах и файловой системе
Определение Файлом называют именованную последовательность элементов данных (компонент файла), расположенных, как правило, во внешней памяти: Ø на дискетах, Ø винчестере, Ø CD или других устройствах хранения информации, Ø также устройствах ввода-вывода. В файле может храниться текст, программа, числовые данные, графическое изображение и т. д. Для организации работы с файлами программа на языке Паскаль взаимодействует с операционной системой. 4
5 Файл – набор данных на диске, имеющий имя. Имя файла: 255 символов, нельзя / : * ? ” < > | персональное имя расширение ( «фамилия» ) Курсова по ОАи. П. exe, . com. txt. doc, . docx. bmp, . gif, . jpg . doc Исполняемые программы Текст без оформления Документ (текст + рисунки + …) Рисунки . wav, . mid, . mp 3 Звук. avi, . mpg, . wmv Видеофильмы. pas, . c, . bas Тексты программ
6 Для того чтобы операционная система (ОС) могла размещать файлы на дисках, последние должны быть специальным образом размечены (форматированы). Разметка осуществляется средствами используемой ОС. Как правило, диски хранят большое количество файлов (количество их на жестких дисках обычно исчисляется тысячами). Для удобства и ускорения работы с таким количеством файлов применяется та или иная файловая система.
7 Файловая система – это порядок размещения файлов на диске. • одноуровневая каталог размер файлы дата изменения vasya. txt 360 байт Примеры. doc 13 Кб Я. bmp 1, 28 Мб номер начального блока (кластера) на диске 12. 03. 2007 25. 04. 2007 13. 09. 2006 25 230 1235 • самый простой вариант • все файлы «в куче» , сложно разбираться • ограниченный объем каталога (512 записей)
Файловая система • многоуровневая (дерево) Диск C: autoexec. bat Файлы в корневом каталоге Документы План. doc Отчет. doc Папка (каталог) – объединяет файлы и вложенные папки Фото 2006 Я. jpg Шарик. jpg Корневой каталог – главный каталог диска. 2007 Ку. jpg Зя. jpg Видео файлы Кузя. avi Винни-Пух. wmv Вложенная папка (подкаталог) – это папка, расположенная внутри другой папки. файлы папка 8
Файловая система • многоуровневая (дерево) дерево папок: Диск C: Фото Документы 2006 Видео 2007 корень Рабочая папка (текущий каталог) – папка, с которой в данный момент работает пользователь. 9
Адреса файлов Полный адрес файла = путь + имя файла диск имя файла C: Фото2007Ку. jpg папки Путь к файлу – это перечисление папок (каталогов), в которых он находится, сверху вниз (начиная с диска). Сетевой адрес: имя компьютера \SERVERВидео2007Зя. avi Примеры: C: SERVERВидео2007Зя. avi A: autoexec. bat \work 3ИгрыHoverhover. exe D: WindowsTempСправка. txt E: Реферат. doc ? Какие файлы находятся в корневом каталоге? 10
Маски Маска – это обозначение для группы файлов. * – любое количество любых символов ? – один любой символ Примеры: *. * *. doc a*. ? *x*. ? ? * *z. a? все файлы с расширением. doc имя файла начинается с «a» , расширение из 1 символа имя файла содержит «x» , расширение не менее 2 символов имя файла заканчивается на «z» , расширение начинается «a» , всего 2 символа 11
Папки Windows Рабочий стол Мои документы Мой компьютер Сетевое окружение Мои рисунки Диск С: Вся сеть Моя музыка Мои видеозаписи CD (DVD) Корзина Диск D: Учебники на Server Диск A: Задания на Server Диск E: Диск F: флэш-диск сетевые ресурсы Диск Z: сетевой диск 12
Логические диски в Windows A: , B: дискеты дисковод C: винчестер, загрузочный диск C: D: E: D: … Z: винчестер, CD, DVD, флэш-диск, сетевой диск (X: \SERVERИгры) 13
14 2. Файлы языка Паскаль
15 В Паскале файл определяется как последовательность компонентов, относящихся к одному типу: Ø файл записей, Ø файл целых чисел, Ø файл строк Ø и т. п. Особенностью файлов по сравнению с другими структурными типами данных является то, что в любой момент доступен только один компонент. Количество компонентов файла заранее не определяется. Максимальный размер файла, размещенного во внешней памяти, ограничивается лишь техническими возможностями вычислительной системы.
Когда нужно использовать файлы 16 ü Файлы полезны, если объем входных данных превосходит посильный при ручном вводе. (Крайним является случай, когда входные или выходные данные заведомо не могут поместиться в оперативной памяти. ) ü Файлы нужны, если приходится многократно вводить одну и ту же информацию, с минимальными изменениями или вовсе без изменений (например, при отладке программы). ü Файлы необходимы, если нужно сохранять информацию о результатах работы программы, полученных при вводе различных входных данных (то есть: при поиске ошибок в программе).
17 Разновидности файлов Файлы Текстовые Бинарные только текст без оформления, могут содержать любые не содержат управляющих символы кодовой таблицы символов (с кодами < 32) *. doc, *. exe, ACSII (1 байт на символ) UNICODE (2 байта на символ) *. bmp, *. jpg, *. txt, *. log, *. html возможно создавать, просматривать и редактировать "вручную" - в любом текстовом редакторе; при считывании данных не требуется заботиться об преобразовании Папки (каталоги) *. wav, *. mp 3, *. avi, *. mpg информация записывается по байтам и потому не доступна для просмотра или редактирования в удобных для человека текстовых редакторах; зато такие файлы более компактны, чем текстовые
Разновидности файлов 18 Бинарные файлы бывают двух видов Ø типизированные, Ø нетипизированные. К типизированным относятся файлы, содержащие данные строго определенного типа. Обычно такие файлы представляются собой наборы записей. К нетипизированным относятся двоичные файлы, которые могут содержать любые совокупности байтов данных без привязки к какому-нибудь одному типу.
Логические устройства 19 Логические устройства используют для организации обмена информацией с основными устройствами вводавывода, такими как дисплей, клавиатура и т. п. Логические устройства имеют стандартные имена, например: Ø CON – консоль: при выводе данных соответствует экрану, при вводе – клавиатуре; Ø PRN – принтер; Ø NUL – «пустое устройство» , обычно заменяет устройство вывода отладочной информации после завершения отладки программы.
Логические устройства 20 В отличие от дисковых файлов с логическими устройствами операции ввода-вывода осуществляют только последовательно, так как Ø при выполнении операций вывода данные передаются на устройство покомпонентно, Ø а при выполнении операций ввода – покомпонентно запрашиваются с него.
Организация файла 21 Физически операции ввода-вывода с файлами выполняются с использованием специального буфера. Так, выводимые записи вначале помещаются в буфер, откуда переписываются в файл по мере заполнения буфера, а вводимые читаются из буфера, куда они были предварительно помещены. Использование буферов позволяет существенно повысить скорость выполнения операций вводавывода с файлом, так как на одну операцию вводавывода с дисководом, которая выполняется сравнительно медленно, обычно приходятся десятки операций чтения из буфера.
Организация файла Для дисковых файлов принципиально возможны Ø не только последовательный, Ø но и произвольный доступ, при котором чтение информации осуществляется из указанного места. 22
Организация файла 23 Доступ к компоненту файла осуществляется через указатель файла. При выполнении операции чтения или записи указатель автоматически перемещается на следующий компонент:
Описание файлов Для идентификации файлов используют файловые переменные. Файловая переменная не может быть задана константой. В зависимости от способа представления информации различают три типа файлов, соответственно различаются и способы описания файловых переменных 24
Описание типизированных файлов Файловая переменная типизированного файла описывается как: Туре <идентификатор файловой переменной> = file оf <тип компонента>; где <тип компонента> - любой тип данных, кроме файлового. Типизированные файлы используют, когда обрабатывают хранящуюся в файле последовательность компонентов одинаковой длины (чисел, записей и т. п. ). 25
Описание текстовых файлов Файловая переменная текстового файла описывается как: Туре <идентификатор файловой переменной> = text; Текстовые файлы используют для работы с текстами, представленными в виде строк переменной длины. 26
Описание нетипизированных файлов Файловая переменная нетипизированного файла описывается как: Туре <идентификатор файловой переменной> = file; Нетипизированные файлы применяют для организации скоростного обмена между внешней и оперативной памятью физическими записями указанной длины без преобразования и обработки. 27
Описание файлов Как и любая переменная языка Паскаль, файловая переменная может быть описана в инструкции объявления переменных. Например: Var F 1: file of real; F 2: file; F 3: text; или с предварительным объявлением типа: Туре FF = file of integer; Var F 1: FF; 28
Описание файлов При необходимости файловую переменную допускается передавать в подпрограмму через параметры. Однако следует помнить, что с этой целью можно использовать только параметры-переменные. Например: Туре FF = file of integer; Procedure Print (Var F 1: FF); 29
30 Работа с файлом включает: Ø инициализацию файловой переменной – установление связи файловой переменной с файлом; Ø открытие файла – подготовку файла для выполнения операций ввода/вывода; Ø обработку компонентов файла – выполнение операций ввода-вывода; Ø закрытие файла (при повторном открытии файл закрывается автоматически).
Инициализация файловой переменной Связь между физическим устройством (дисководом или внешним устройством) и файловой переменной устанавливается специальной процедурой. Процедура Assign (Var f; st: string) инициализирует файловую переменную f, связывая ее с файлом или логическим устройством, определенным строкой st. Если файл находится в текущем каталоге, то достаточно указать имя файла и его расширение. В противном случае необходимо указать полное имя файла 31
Инициализация файловой переменной Например: Туре F = text; Var f 1, f 2, f 3: F; . . . Assign (fl, 'T 1. dat'); {связывание файловой переменной с файлом в текущем каталоге} Assign (f 2, 'd: ivaa. dat'): {связывание файловой переменной с файлом в указанном каталоге} Assign(f 3, 'CON'); {связывание файловой переменной с консолью} 32
Открытие файла предполагает указание направления передачи данных. В Паскале файл можно открыть Ø для чтения Ø и для записи. Текстовый файл можно открыть также для добавления строк. В типизированный файл, открытый для чтения, можно дописывать новые записи или писать в нем новые записи на место старых. 33
Открытие файла 34 Процедура Re. Set(Var f) открывает файл, определенный файловой переменной f для чтения. При выполнении этой процедуры указатель файла устанавливается на первый компонент файла (физически первый блок записей считывается в буфер). Логическое устройство в этом случае готовится к выполнению операций ввода.
Открытие файла 35 При открытии для чтения несуществующего файла регистрируется ошибка выполнения, а функция l. OResult типа Word возвращает значение, отличное от 0 (см. далее описание функции). Отключив контроль операций ввода-вывода и используя функцию l. OResult, можно организовать проверку наличия файла с указанным именем на диске: Var f: file of char; Begin Assign(f, 'a. dat'); {инициализация файловой переменной} {$ I- } {отмена контроля ошибок ввода-вывода} Re. Set (f); {открытие файла для чтения} {$ I+ } {включение контроля ошибок} if IOResult <>0 then Write. Ln ('Файл не существует'); else Write. Ln('Файл существует');
Открытие файла 36 Процедура Re. Write(Var f) открывает файл, определенный файловой переменной f, для записи. Ø При открытии для записи существующего файла старый файл уничтожается без предварительной проверки и выдачи предупреждения пользователю. Ø Если файла с таким именем не существовало, то он создается и подготавливается к записи (физически – очищается буфер). Логическое устройство при этом подготавливается к приему информации.
37 Открытие файла Процедура App. End(Var f: text) открывает текстовый файл, определенный файловой переменной f, для добавления строк. При открытии для добавления строк указатель файла устанавливается на конец файла, и, соответственно, все строки, выводимые в файл, дописываются к уже существующему файлу.
Открытие файла 38 Любой программе без объявления, инициализации файловой переменной и открытия доступны два файла со стандартными файловыми переменными: Ø INPUT – чтение со стандартного устройства ввода; Ø OUTPUT – вывод на стандартное устройство вывода. Это текстовые файлы, используемые для выполнения элементарных операций ввода-вывода. В операторах ввода-вывода файловые переменные этих файлов обычно не указывают. Остальные файлы становятся доступными только после связывания файловой переменной с файлом или логическим устройством и открытия файла. Стандартным устройством ввода по умолчанию является клавиатура. Стандартным устройством вывода – экран дисплея.
Обработка компонентов файла 39 На базе этих операций выполняют более сложные операции: Ø создание файла – занесение в файл требуемых записей; Ø модификация файла – изменение всех или нескольких записей, добавление и удаление записей; Ø поиск нужной информации в файле. Выполнение этих операций осуществляется по-своему для каждого типа файла (см. параграфы далее).
Закрытие файла 40 Закрытие файла, открытого для записи или чтения, осуществляется процедурой Close(Var f) При этом вновь созданный файл регистрируется в каталоге. ! Поскольку любое обращение к диску осуществляется через буферную память, часть данных, выводимых в файл, может остаться в буфере. Процедура закрытия файла обеспечивает вывод оставшихся компонентов из буфера в файл. Связь файловой переменной с файлом при закрытии сохраняется, и при повторном использовании этого же файла процедуру Assign применять еще раз не требуется.
Переменная типа 41 «текстовый файл» : Принцип сэндвича var f: text; I этап. открыть файл : • связать переменную f с файлом assign(f, 'qq. txt'); • открыть файл (сделать его активным, приготовить к работе) reset(f); {для чтения} rewrite(f); {для записи} II этап: работа с файлом read ( f, n ); { ввести значение n } write ( f, n ); { записать значение n } writeln ( f, n ); {c переходом на нов. строку } III этап: закрыть файл close(f);
Работа с файлами 42 Особенности: • имя файла упоминается только в команде assign, обращение к файлу идет через файловую переменную • файл, который открывается на чтение, должен существовать • если файл, который открывается на запись, существует, старое содержимое уничтожается • данные записываются в файл в текстовом виде • при завершении программы все файлы закрываются автоматически • после закрытия файла переменную f можно использовать еще раз для работы с другим файлом
Стандартные процедуры и функции обслуживания файлов 43 Для взаимодействия с файловой системой определены стандартные процедуры и функции, которые применимы к файлам любых типов.
Стандартные процедуры и функции обслуживания файлов Процедура Re. Name(Var f; name: string) осуществляет переименование файла, определенного файловой переменной f. Новое имя файла задается параметром name. Если в процессе работы программы требуется переименовать файл, открытый для чтения или записи, необходимо предварительно закрыть этот файл. При совпадении нового имени файла с каким-либо уже существующим выдается сообщение об ошибке. 44
Стандартные процедуры и функции обслуживания файлов Процедура Erase(Var f) осуществляет удаление созданного или находящегося в процессе формирования файла. Перед уничтожением файл должен быть закрыт, так как разрешается удалять только закрытые файлы. 45
Стандартные процедуры и функции обслуживания файлов 46 Функция EOF(Var f): boolean определяет конец файла. Как было отмечено выше, размер файла при его создании не фиксируется. Поэтому в процессе работы требуется проверка достижения конца файла. Функция принимает значение TRUE, если указатель стоит в конце файла (последней записи). При этом, если производится чтение, то это означает, что файл исчерпан, а если идет запись, то новая запись дописывается в конец файла. Функция принимает значение FALSE, если конец файла еще не достигнут.
Стандартные процедуры и функции обслуживания файлов 47 Функция IOResult(Var f): word возвращает код правильности выполнения операций ввода/вывода. Если ошибок не зафиксировано, то функция возвращает 0. Информация об ошибках может быть получена и обработана в режиме компилятора {$ I-} – отключение контроля ошибок ввода/вывода.
Стандартные процедуры и функции обслуживания файлов Процедура Truncate(Var f) обрезает файл, оставляя компоненты до того, на который ссылается указатель файла (кроме текстовых файлов). 48
Стандартные процедуры и функции обслуживания файлов Процедура Ch. Dir(path: string) изменяет текущий каталог: назначает текущим каталог, указанный параметром path. 49
Стандартные процедуры и функции обслуживания файлов Процедура Get. Dir(drive: word; Var dir: string) возвращает в переменную dir имя текущего каталога на указанном устройстве, где устройство drive: 0 – устройство по умолчанию; 1 – диск А; 2 – диск В и т. д. 50
Стандартные процедуры и функции обслуживания файлов Процедура Mk. Dir(dir: string) создает новый каталог. Строка dir определяет путь и новое имя. 51
Стандартные процедуры и функции обслуживания файлов Процедура Rm. Dir(dir: string) удаляет каталог с именем, указанным в переменной dir. Каталог должен быть пустым. 52
53 3. Текстовые файлы
Структура текстового файла 54 Текстовый файл - это файл, компонентами которого являются символьные строки переменной длины, заканчивающиеся специальным маркером конца строки: Маркер конца строки - это последовательность из двух специальных символов по таблице ASCII «#13, #10» . Символ с кодом 13 интерпретируется в компьютере как команда установки курсора в начало строки, а символ с кодом 10 - как команда перехода на следующую строку. Такая комбинация кодов вводится при нажатии клавиши ENTER.
55 Текстовый файл можно открыть для записи, чтения и добавления записей в конец. Файл, открытый для записи, не может использоваться для чтения и наоборот. При открытии файла для добавления система проверяет, не был ли файл открыт для чтения или записи, и если такое открытие имело место, то производится сначала закрытие файла, а затем уже открытие для добавления.
56 Текстовые файлы используют для хранения и обработки текстовой информации: Ø символов, Ø строк, Ø символьных массивов. Логические и числовые данные при записи в текстовые файлы должны преобразовываться в символьные строки. Следует иметь в виду, что при необходимости текстовый файл может быть создан или прочитан любым текстовым редактором, в том числе и текстовым редактором.
Стандартные процедуры и функции обслуживания текстовых файлов Функция EOLn( Var f): boolean возвращает TRUE, если во входном текстовом файле достигнут маркер конца строки. При отсутствии файловой переменной проверяется стандартный файл INPUT, который обычно связан с клавиатурой. 57
Стандартные процедуры и функции обслуживания текстовых файлов Процедура Read( Var f: text; vl, v 2, . . . , vn) обеспечивает ввод символов, строк и чисел. Список ввода представляет собой последовательность из одной или более переменных типа CHAR, STRING, а также любого целого и вещественного типа. При отсутствии файловой переменной ввод осуществляется из стандартного файла INPUT. 58
Стандартные процедуры и функции обслуживания текстовых файлов 59 При вводе значений переменных типа CHAR выполняется чтение одного символа из файла, считанное значение присваивается очередной переменной из списка ввода. Символы вводятся подряд, а не через пробел, как числа. Если перед выполнением чтения указатель файла Ø достиг конца очередной строки, то результатом чтения будет символ #13, Ø а если был достигнут конец файла, то – символ #26.
Стандартные процедуры и функции обслуживания текстовых файлов: Read 60 При вводе переменных типа STRING количество считанных процедурой и помещенных в строку символов равно максимальной длине строки, если раньше не встретились маркеры конца строки или конца файла, которые в строку не включаются. Символы, выходящие за размер максимальной длины строки, отбрасываются. ! Новое обращение к процедуре Read вернет пустую строку. Следовательно, процедура Read не в состоянии читать последовательность строк, так как первая строка будет прочитана правильно, а все последующие окажутся пустыми.
Стандартные процедуры и функции обслуживания текстовых файлов: Read 61 При вводе числовых данных процедура Read пропускает все пробелы, знаки табуляции и маркеры до первого значащего символа и читает строку до пробела, знака табуляции или маркера. Полученная подстрока преобразуется из символьного во внутреннее представление в соответствии с типом значения и присваивается следующей переменной из списка. Если нарушен формат, то фиксируется ошибка вводавывода. Если достигнут маркер конца файла, то переменной присваивается значение 0, причем никаких сообщений в этом случае не выдается.
Стандартные процедуры и функции обслуживания текстовых файлов: Read 62 Ввод логических констант процедурами Read. Ln не предусмотрен. Чтение с клавиатуры осуществляется через буфер, который передается процедуре при нажатии клавиши ENTER и имеет размер 127 байт, поэтому ввести с клавиатуры строку большего размера нельзя.
Стандартные процедуры и функции обслуживания текстовых файлов 63 Процедура Read. Ln( Var f; vl, v 2, . . . , vn) также обеспечивает ввод символов, строк и чисел. Процедура использует те же правила ввода, что и процедура Read, но после чтения последней переменной оставшаяся часть строки до маркера конца строки пропускается, так что следующее обращение к Read. Ln или Read начнется с первого символа новой строки. Процедура может быть вызвана без указания списка ввода, что приведет к пропуску всех символов текущей строки до маркера конца строки.
Стандартные процедуры и функции обслуживания текстовых файлов 64 Процедуры Read и Read. Ln могут использоваться без указания файловой переменной. Тогда операция чтения осуществляется из стандартного файла INPUT. Использование процедуры Read. Ln без параметров после процедуры Read приведет к очистке буфера ввода. Применение этой же процедуры без предшествующей ей процедуры Read переводит программу в состояние ввода, т. е. выполнение программы приостанавливается до нажатия клавиши ENTER, что может использоваться для организации паузы на время просмотра содержимого экрана.
65 Последовательный доступ • при открытии файла курсор устанавливается в начало assign ( f, 'qq. txt' ); reset ( f ); 12 5 45 конец файла (end of file, EOF) 67 56● • чтение выполняется с той позиции, где стоит курсор • после чтения курсор сдвигается на первый непрочитанный символ read ( f, x ); 12 5 45 67 56●
66 Последовательный доступ • чтение до конца строки readln ( f, x ); конец строки (end of line, EOL) 12 5 45¤ 36 67¤ • как вернуться назад? close ( f ); reset ( f ); { начать с начала } 56●
Стандартные процедуры и функции обслуживания текстовых файлов 67 Процедура Write( Var f; vl, v 2, . . . , vn) обеспечивает вывод данных в текстовый файл или передачу их на логическое устройство. Список вывода – последовательность из одного или более выражений типа CHAR, STRING, BOOLEAN, а также целого или вещественного типов. При выводе числовых значений последние преобразуются в символьное представление. При отсутствии файловой переменной вывод осуществляется в стандартный файл OUTPUT, который обычно назначен на экран.
Стандартные процедуры и функции обслуживания текстовых файлов Любой параметр из списка вывода может иметь формат: <параметр> [: <целое 1> [: < целое 2> ]], где <целое 1> и <целое 2> интерпретируются в соответствии с правилами, описанными в параграфе «Ввод-вывод данных» Темы 2 68
Стандартные процедуры и функции обслуживания текстовых файлов 69 Процедура Write. Ln( Var f; vl, v 2, . . . , vn) обеспечивает вывод информации в текстовый файл или ее передачу на логическое устройство вывода. При отсутствии файловой переменной вывод осуществляется в стандартный файл OUTPUT, который обычно связан с дисплеем. Процедура полностью идентична процедуре Write, за исключением того, что выводимая строка символов завершается символами #13 и #10. При вызове Write. Ln допускается опускать список вывода, в этом случае в файл передается маркер конца строки (при выводе на экран это приведет к переводу курсора в начало следующей строки).
Стандартные процедуры и функции обслуживания текстовых файлов Функция Seek. EOLn( Var f ): boolean пропускает все пробелы и знаки табуляции до маркера конца строки или до первого значащего символа и возвращает TRUE при обнаружении маркера. Если файловая переменная не указана, то функция проверяет стандартный файл INPUT. 70
Стандартные процедуры и функции обслуживания текстовых файлов 71 Функция Seek. EOF( Var f ): boolean пропускает все пробелы, знаки табуляции и маркеры конца строки до маркера конца файла или до первого значащего символа и возвращает TRUE при обнаружении маркера. Если файловая переменная отсутствует, то функция проверяет стандартный файл INPUT.
Пример 1 72 Разработать программу, которая формирует текстовый файл из 26 строк, содержащих случайное количество соответствующих прописных букв латинского алфавита. Например: ААААА ВВВВВ С DDDDDDDDDDD ЕЕЕЕЕЕЕ и т. д.
73 Пример 1 Program Form. Text. File; Var f: text; {файловая переменная для текстового файла} а: char; n, i: integer; fname, st: string[30]; Begin Write. Ln('Введите имя файла'); Read. Ln(fname); Assign(f, fname); {инициализируем файловую Re. Write(f); Randomize; переменную} {открываем файл для записи} {инициализируем датчик случайных чисел}
74 Пример 1 for а: ='А' to 'Z' do begin {формируем строки} n: =Random(30)+l; st: =''; for i: =l to n do st: =st+a: Write. Ln(f, st); {записываем строку Write. Ln(st); end; Close(f); End. в текстовый файл} {для контроля - выводим ее на экран} {закрываем файл}
75 Поскольку компоненты текстового файла могут иметь различную длину, возможна только последовательная их обработка (запись, чтение и поиск). Любой вид модификации файла, кроме добавления записей в конец, выполняется с перезаписью информации в другой файл. Так, для того чтобы исключить некоторую запись, необходимо переписать все строки, кроме подлежащей исключению, в другой текстовый файл. При этом обычно старый файл удаляют, новый – переименовывают, присваивая ему имя исходного файла, и файловую переменную связывают с измененным файлом.
Пример 2 Разработать программу, которая удаляет из текстового файла «пустые» строки: ü строки, не содержащие символов, ü и строки, содержащие только пробелы и знаки табуляции. Поскольку в результате обработки часть строк текстового файла будет удалена, нам потребуется создать специальный файл, куда будут помещены непустые строки файла. 76
Пример 2 77 Program ex; Var f 1, f 2: text; {файловые переменные текстовых файлов} st, name: string; Begin Write. Ln('Введите имя файла: '); Read. Ln(name); Assign(f 1, name); {иниц-ем файловую переменную} {$I-} {проверяем существование файла} Reset(f 1); {$I+} if IOResult=0 then begin {если файл с заданным именем существует} Assign(f 2, 'temp. dat'); {иниц-ем новый файл} Rewrite(f 2); {открываем новый файл для записи}
78 Пример 2 while not EOF(f 1) do begin {пока не достигнут конец файла} if Seek. EOLn(f 1) then Read. Ln(f 1, St) {если строка пустая, то пропускаем ее} else begin Read. Ln(f 1, st); {читаем строку} Write. Ln(f 2, st); {записываем ее в новый файл} end; Close(f 1); {закрываем старый файл} Close(f 2); {закрываем новый файл} Erase(f 1); {удаляем старый файл} Re. Name(f 2, name); {переименовываем новый файл} end else Wnte. Ln('Файл с таким именем не найден'); End.
79 Пример 3 Задача: в файле input. txt записаны числа (в столбик), сколько их – неизвестно. Записать в файл output. txt их сумму. ? Можно ли обойтись без массива? Алгоритм: 1. Открыть файл input. txt для чтения. 2. S : = 0; 3. Если чисел не осталось, перейти к шагу 7. 4. Прочитать очередное число в переменную x. 5. S : = S + x; цикл с условием «пока есть данные» 6. Перейти к шагу 3. 7. Закрыть файл input. txt. 8. Открыть файл output. txt для записи. 9. Записать в файл значение S. 10. Закрыть файл output. txt.
80 Пример 3 program qq; var s, x: integer; f: text; begin assign(f, 'input. txt'); reset(f); s : = 0; while not eof(f) do begin readln(f, x); s : = s + x; end; close(f); логическая функция, возвращает True, если достигнут конец файла assign(f, 'output. txt'); rewrite(f); writeln(f, 'Сумма чисел ', s); close(f); end. запись результата в файл output. txt
Задания 81 В файле input. txt записаны числа, сколько их – неизвестно. « 4» : Найти среднее арифметическое всех чисел и записать его в файл output. txt. « 5» : Найти минимальное и максимальное числа и записать их в файл output. txt.
Пример 4: обработка массивов 82 Задача: в файле input. txt записаны числа (в столбик), сколько их – неизвестно, но не более 100. Переставить их в порядке возрастания и записать в файл output. txt. ? Можно ли обойтись без массива? Проблемы: 1. для сортировки надо удерживать в памяти все числа сразу (массив); 2. сколько чисел – неизвестно. Решение: 1. выделяем в памяти массив из 100 элементов; 2. записываем прочитанные числа в массив и считаем их в переменной N; 3. сортируем первые N элементов массива; 4. записываем их в файл.
Пример 4: чтение данных в массив Глобальные переменные: var A: array[1. . 100] of integer; f: text; Функция: ввод массива, возвращает число элементов function Read. Array: integer; var i: integer; begin assign(f, 'input. txt'); reset(f); i : = 0; цикл заканчивается, если достигнут конец файла или прочитали 100 чисел while (not eof(f)) and (i < 100) do begin i : = i + 1; readln(f, A[i]); end; close(f); Read. Array : = i; end; 83
84 Пример 4 program qq; var A: array[1. . 100] of integer; f: text; N, i: integer; function Read. Array: integer; . . . end; Begin N : = Read. Array; { сортировка первых N элементов } assign(f, 'output. txt'); rewrite(f); for i: =1 to N do writeln(f, A[i]); close(f); end. вывод отсортированного массива в файл
Задания 85 В файле input. txt записаны числа (в столбик), известно, что их не более 100. « 4» : Отсортировать массив по убыванию последней цифры и записать его в файл output. txt. « 5» : Отсортировать массив по возрастанию суммы цифр и записать его в файл output. txt.
Пример 5: обработка текстовых данных 86 Задача: в файле input. txt записаны строки, в которых есть слово-паразит «короче» . Очистить текст от мусора и записать в файл output. txt. Файл input. txt : Мама, короче, мыла, короче, раму. Декан, короче, пропил, короче, бутан. А роза, короче, упала на лапу, короче, Азора. Каждый, короче, охотник желает, короче, знать, где. . . Результат - файл output. txt : Мама мыла раму. Декан пропил бутан. А роза упала на лапу Азора. Каждый охотник желает знать, где сидит фазан.
Пример 5: обработка текстовых данных Алгоритм: 87 пока не кончились данные 1. Прочитать строку из файла (readln). 2. Удалить все сочетания ", короче, " (Pos, Delete). 3. Записать строку в другой файл. 4. Перейти к шагу 1. Обработка строки s: искать «, короче, » repeat i : = Pos(', короче, ', s); if i <> 0 then Delete(s, i, 9); until i = 0; удалить 9 символов Особенность: надо одновременно держать открытыми два файла (один в режиме чтения, второй – в режиме записи).
Работа с двумя файлами одновременно program qq; файловые var s: string; переменные i: integer; открыть файл f. In, f. Out: text; для чтения begin assign(f. In, 'input. txt'); reset(f. In); открыть файл assign(f. Out, 'output. txt'); для записи rewrite(f. Out); { обработать файл } close(f. In); close(f. Out); end. 88
Полный цикл обработки файла пока не достигнут конец файла while not eof(f. In) do begin readln(f. In, s); обработка строки repeat i : = Pos(', короче, ', s); if i <> 0 then Delete(s, i, 9); until i = 0; writeln(f. Out, s); end; запись «очищенной» строки 89
Задания 90 В файле input. txt записаны строки, сколько их – неизвестно. « 4» : Заменить все слова «короче» на «в общем» и записать результат в файл output. txt. « 5» : Вывести в файл output. txt только те строки, в которых больше 5 слов (слова могут быть разделены несколькими пробелами).
91 4. Типизированные файлы
Организация типизированного файла Типизированный файл – это файл, все компоненты которого одного типа, заданного при объявлении файловой переменной. Компоненты файла хранятся на диске во внутреннем (двоичном) формате и нумеруются с 0. Компонентами таких файлов могут быть как простые (integer, longint, real и т. д. ) типы данных, так и структурированные типы данных (массивы, записи и др. ) 92
Организация типизированного файла Если посмотреть такой файл любым текстовым редактором, то можно распознать только символьную информацию, на месте же чисел в файле будут располагаться пробелы или символы псевдографики. 93
Стандартные процедуры и функции обслуживания типизированных файлов Процедура Read(Var f; с1, с2, . . . , сn) осуществляет чтение очередных компонентов типизированного файла. Список переменных ввода содержит одну или несколько переменных того же типа, что и компоненты файла, разделенных запятыми. Если файл исчерпан, обращение к процедуре вызывает ошибку ввода-вывода. 94
Стандартные процедуры и функции обслуживания типизированных файлов Процедура Write(Var f; с1, с2, . . . , сn) осуществляет запись данных в типизированный файл. Список вывода содержит одно или более выражений того же типа, что и компоненты файла, разделенных запятыми. ! При работе с типизированными файлами процедура Writeln не используется. 95
Стандартные процедуры и функции обслуживания типизированных файлов Процедура Seek(Var f; numcomp: word) осуществляет установку указателя файла (переход) на компонент файла с номером numcomp. Например, Seek(f, 9); осуществляет переход к десятой записи в файле f. 96
Стандартные процедуры и функции обслуживания типизированных файлов Функция File. Size(Var f): longint возвращает количество компонент файла, указанного файловой переменной. Может использоваться для установки на конец файла совместно с Seek() или на последнюю запись файла соответственно: Seek(f, File. Size(f)); Seek(f, File. Size(f)-1); 97
Стандартные процедуры и функции обслуживания типизированных файлов 98 Функция File. Pos(Var f): longint возвращает порядковый номер компонента, который будет обрабатываться следующей операцией ввода-вывода.
Обработка типизированного файла 99 После открытия файла для чтения или записи указатель файла стоит в его начале и указывает на первый компонент, имеющий номер 0. После каждого чтения или записи указатель сдвигается к следующему компоненту файла. Поскольку длина каждой компоненты файла строго постоянна, помимо последовательного возможно осуществление прямого доступа к компонентам файла. По той же причине, если требуется изменить компонент файла, то не обязательно переписывать компоненты в другой файл, а достаточно установить указатель файла на изменяемый компонент и записать новый компонент на место старого. Удаление компонент обычно требует перезаписи файла.
Обработка типизированного файла 100 Добавление компонентов в конец файла выполняется в режиме чтения. Для этого указатель файла устанавливается на его конец (как показано выше), после чего все выводимые компоненты дописываются в конец файла. Добавление компонентов в середину или начало файла может выполняться следующим образом: Ø определяем место, в которое должны быть добавлены элементы, Ø все последующие компоненты переписываем во временный файл, Ø вставляем новые компоненты Ø дописываем в файл компоненты, переписанные во временный файл.
Пример 6 Разработать программу, создающую файл, компонентами которого являются символы, введенные с клавиатуры. Затем эта программа должна ü изменять символы, записанные в файл, ü организовывать чтение символов из файла попеременно с начала и с конца (прямой доступ), ü находить указанный символ в файле и удалять его из файла. 101
102 Пример 6 Program ex; Var f, f 1: file of char; { две файловые переменные} ch, i: char; j: longint; name: strmg[8]; Begin Write. Ln('Введите имя файла: '); Read. Ln(name); {создание и открытие файла} Assign(f, name + '. dat'); {связываем файл с файловой переменной} {открываем файл для записи (создаем)} Re. Write(f); Write. Ln('Вводите символы или CTRL-Z: ');
103 Пример 6 {занесение записей в файл} while not EOF do {пока не введено CTRL-Z с клавиатуры} begin Read. Ln(ch); Write(f, Ch); end; Write. Ln; {вводим символ с клавиатуры} {записываем символ в файл} {последовательное чтение записей из файла} Re. Set(f); {открываем файл для чтения} while not EOF(f) do {пока не достигнут конец файла} begin Read(f, ch); {читаем символ из файла} Write(ch, ' '); {выводим символ на экран} end; Write. Ln;
Пример 6 104 {изменение записей в файле} Re. Set(f); {открываем файл для чтения} while not EOF(f) do {пока не достигнут конец файла} begin Read(f, i); {читаем символ из файла} Write(i, ' '); {выводим символ на экран} i: =chr(ord(i)+10); {изменяем символ} Write. Ln(i); {выводим на экран измененный символ} Seek(f, File. Pos(f)-1); {возвращаемся на 1 компонент} Write(f, i); {перезаписываем символ} end; Write. Ln;
Пример 6 105 {попеременное чтение записей с начала и конца файла} Re. Set(f); {открываем файл для чтения} j: =0; {устанавливаем номер компонента равным 0} while not EOF(f) do {пока не достигнут конец файла} begin Read(f, i); {читаем символ из начала файла} Write(i); {выводим символ на экран} Seek(f, File. Size(f) - File. Pos(f)); {устанавливаем указатель для чтения из конца файла} Read(f, i); {читаем символ из конца файла} Write(i); {выводим символ на экран} j: =j+l; {увеличиваем номер компонента} Seek(f, j); {устанавливаем указатель на следующий от начала компонент} end; Write. Ln (’Введите символ для удаления: ’); Read. Ln(ch);
Пример 6 106 {подготовка к удалению записей: переименование исходного файла и открытие нового файла с тем же именем} Close(f); {закрываем файл} Re. Name(f, name + '. bak'); {переименовываем файл} Re. Set(f); {открываем файл для чтения} Assign(f 1, name + '. dat'); {связываем новый файл с переменной} Re. Write(f 1); {открываем новый файл для записи} {удаление записей - перепись остающихся записей в др. файл} while not EOF(f) do begin Read(f, i); {читаем символ из файла} if i<>ch then Write(f 1, i); {если символ не подлежит удалению, то записываем его в новый файл} end; Erase(f); {удаляем старый файл, после закрытия в нем ничего не изменилось, поэтому повторно его можно не закрывать}
Пример 6 {последовательное чтение записей из нового файла} Re. Set(f 1); {открываем новый файл для чтения} while not EOF(f 1) do begin Read(f 1, Ch); {читаем из файла} Write(ch, ' '); end; Write. Ln; End. 107
Пример 7 Разработать программу, которая создает файл, содержащий список фамилий и даты рождения. Осуществить поиск в этом файле даты рождения по заданной фамилии. 108
109 Пример 7 Program ex; Type fam=record {тип запись «сведения о сотрудниках» } ff: string[20]; {фамилия} year: word; {год рождения} month: 1. . 12; {месяц рождения} day: 1. . 31 {день рождения} end; Var f: file of fam; {файловая переменная «файл сотрудников» } fb: fam; n, i: integer; fff: string; key: boolean; Begin Assign(f, 'a. dat'); Re. Write(f); {открываем файл для записи} Write. Ln('Введите данные или CTRL-Z');
Пример 7 110 while not EOF do begin {цикл, пока не введено CTRL-Z} Read. Ln(fb. ff, fb. year, fb. month, fb. day); {вводим данные по полям, фамилию вводим в отдельной строке, т. к. ввод строки завершается нажатием клавиши Enter} Write(f, fb); {запись в файл как один компонент} end; Close(f); {закрываем файл} Write. Ln('Введите фамилию'); Readln(fff); key: =false; {устанавливаем признак «запись не найдена» } Re. Set(f); {открываем файл для чтения}
Пример 7 111 while (not EOF(f)) and (not key) do begin {пока не обнаружен конец файла и не найдена запись} Read(f, fb); {читаем запись из файла} if fb. ff=fff then begin {если фамилии совпадают, то выводим данные} Write. Ln('Дaтa: ', fb. year, fb. month: 3, fb. day: 3); key: =true; {устанавливаем признак «запись найдена» } end; if not key then {если признак не установлен} Write. Ln('Hem данных') ; Close(f); {закрываем файл} End.
Пример 8 112 Разработать программу, которая выводит данные о компакт -дисках, содержащиеся в типизированном файле. program Audioln; Type {Структура для хранения данных об одной дорожке} Track = record Name: string[50]; {Название дорожки} Hours: 0. . 3; {Часы} Minutes: 0. . 59; {Минуты} Seconds: 0. . 59; {Секунды} end;
113 Пример 8 {Структура для хранения информации о диске} CD = record Author: string[20]; Title: string[50]; Year: integer; Kind: string[10]; case Tracks: byte of 1: (Track 1: Track); {Автор} {Название} {Год} {Жанр} {Количество дорожек} {Если дорожек больше одной, тогда информация хранится в виде массива} [2. . 20]: (ATracks: array[1. . 20] of Track); end; Var c: char; i, j: byte; FName: string; CDData: CD; F: file of CD; is. Error: boolean;
Пример 8 114 {Процедура ввода данных об одной дорожке} procedure Data. For. Track(var Track. Data: Track); Var hh, mm, sa: string[2]; Timing: string[8]; begin with Track. Data do begin (Преобразовываем в строки значения часов, минут и секунд) Str(Hours, hh); Str (Minutes, mm); Str(Seconds, ss) ; {Формируем строку времени звучания) if Hours = 0 then Timing : = '' else Timing : = hh + ': '; Timing : = Timing + mm + '"' + ss + Chr(39) ; Writeln(num, '-', Name, ' (', Timing, ')'); end;
Пример 8 115 Begin is. Error : = True; while is. Error do begin Write. Ln('Введите имя файла с данными о музыкальных дисках: '); Readln (FName) ; Assign(F, FName); {$ I-} Reset(F); {$ I+} is. Error : = (IOResult > 0); if is. Error then Writeln('Такого файла нет'); end;
Пример 8 116 repeat Writeln('Файл содержит данные о ', File. Size(F), ' дисках: '); Seek(F, 0); {Перемещаемся к первой записи} for i: =0 to File. Size(F)-1 do begin Read(F, CDData); Writeln(i+1, ' - ', CDData. Author, ', ''', CDData. Title, '''') {Отображаем список дисков по 20 на экране} if (((i+1) mod 20)=0) and (i<(File. Size(F)-1)) then begin Writeln('Для промотра остальных дисков нажмите
Пример 8 Writeln('Введите порядковый номер диска для просмотра: '); Readln(num); Seek(F, num-1); {Перемещаемся к указанной записи} Read(F, CDData); Writeln('>>> ', CDData. Author, ', ''', CDData. Title, '''- ', CDData. Year, 'г. (', CDData. Kind, ') <<<'); {Выводим данные о дорожках} if CDData. Tracks =1 then Data. For. Track(CDData. Track 1, 1) else for i: =1 to CDData. Tracks do Data. For. Track(CDData. ATracks[i], i); 117
Пример 8 Write('Ввести данные еще об одном диске (Да/Нет)? '); Readln(с); until с in ['N', 'n', 'Н', 'н']; Close(F); end. 118
Пример 9 119 Следующая программа демонстрирует использование алгоритма бинарного поиска для последовательности, размещенной не в массиве, а в файле прямого доступа (типизированном файле). Разработать программу поиска заданных элементов в упорядоченном типизированном файле целых чисел.
Пример 9 120 Uses CRT; Type Lf: file of integer var f: Lf; name: string; {Поиск элемента х в упорядоченном файле целых чисел f } function searchf (var f: Lf; x: integer): boolean; var nn, i 1, i 2, s, ax, bx, as: integer; Begin reset(f); nn: =File. Size(f); i 1: =0; i 2: =nn-1; seek(f, i 1); Read(f, ax); seek(f, i 2); Read(f, bx); if (x>bx) or (x
Пример 9 while (i 2 -i 1 > 1) do begin s: =(i 2 -i 1)div 2 + i 1; seek(f, s); Read(f, as); if as=x then begin searchf : =true; Exit end; if as
Пример 9 { Ввод искомых элементов и обращение к операции поиска } procedure elements; var x, i, n: integer; begin Writeln('Введите число искомых элементов : '); Read(n); for i: =1 to n do begin Writeln('Введите искомое значение: '); Read(x); if searchf(f, x) then Write. Ln(' число есть') else Write. Ln(' числа нет'); end; Read. Ln end; { procedure elements } 122
Пример 9 { Головная программа } Begin Write. Ln('Введите полное имя файла: '); Read. Ln(name); assign(f, name); {$I-} {проверяем существование файла} reset(f); {$I+} if IOResult = 0 then elements else Write. Ln('*** неверное имя файла'); Read. Ln End. 123
Пример 10 124 Следует отметить, что любой текстовый файл может быть прочитан как типизированный файл с компонентами типа CHAR. В этом случае необходимо учитывать, что маркер конца строки текстового файла рассматривается в символьном представлении как последовательность из двух символов #13 и #10. Разработать программу, которая открывает текстовый файл как типизированный с компонентом типа CHAR и читает его по символу.
125 Пример 10 Program chartextfile; Type ff=file of char; {новый тип - символьный файл} Var f: ff; {файловая переменная типа файл символов} a: char; n, i: integer; fname, st: string[30]; Begin Write. Ln('Bвeдитe имя файла'); Read. Ln(fname); Assign(f, fname); Re. Set(f); {открыть текстовый файл как типизированный на чтение}
Пример 10 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} Write. Ln(st); {выводим сформированную строку} end; Close(f); End. 126