Rationale for Ada 2005: Predefined library
RUSTOPBACKNEXT
ENG |
4. Operational environment
@ Two new packages are added to Ada 2005 in order to aid communication with the operational environment. They are Ada.Environment_Variables and Ada.Directories. @ The package Ada.Environment_Variables has the following specification
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale for Ada 2005: Predefined library
@ENGRUSTOPBACKNEXT4. Операционная среда
@ Два новых пакета добавлены к Аде 2005 чтобы помочь коммуникации с операционной средой. Это - Ada.Environment_Variables и Ada.Directories.
@ Пакет Ada.Environment_Variables имеет следующую спецификацию:
|
@ Этот пакет обеспечивает доступ к переменным среды по имени. Что они означают и поддерживаются ли вообще зависит от реализации. Но у большинства операционных систем есть переменные среды некоторого вида. В противном случае предполагается что реализация будет моделировать их сама.
@ Значения переменной - также зависит от реализации и просто представлено строками.
@ Поведение является прямым. Мы могли бы выяснить, если есть переменная с названием "Ada" и затем читать и печатать ее значение и устанавливать её в Аде 2005 примерно таким образом:
|
@ Процедура Clear с параметром удаляет соответствующую переменную. Таким образом, процедура Clear ("Ada") устраняет ее так что последующий вызов Exists ("Ada") выдаст False. Отметим, что процедура Set фактически очищает соответствующую переменную а затем определяет новую с именем и значением. Процедура Clear без параметра очищает все переменные.
@ Мы можем выполнить итерации по всем переменным, используя процедуру Iterate. Например мы можем распечатать их текущее состояние таким образом:
|
@ Процедура Print_One печатает название и значение переменной переданной параметром. Тогда мы передаем ссылку на эту процедуру процедуре Iterate которая итеративно вызывает процедуру Print_One для каждой переменной среды в свою очередь.
@ Отметим, что у подчиненной процедуры есть и имя (Name) и значение (Value) передаваемые как параметры. Можно было бы посчитать это излишним, так как пользователь может всегда вызвать функцию Value. Однако, у реальных операционных систем может иногда быть несколько переменных с одним и тем же именем; использование двух параметров гарантирует, что пара название - значения правильно согласованы.
@ Попытка неправильно использовать пакет Ada.Environment_Variables например для чтение переменной, которой не существует вызывает исключение Constraint_Error или Program_Error.
@ Есть опасность возникновения конфликта при доступе разных пользователей к одной и той же переменной среды, потому что переменные среды действительно глобально разделены. Кроме того, конфликты могут возникать с самой операционной системой, а так же с программами, написанными на других языках.
@ Специфический пункт состоит в том, что мы не должны вызывать процедуры Set или Clear в процедуре Iterate.
@ Другой пакет - Ада.Directories. Его спецификация:
|
@ У большинства операционных систем файловая система имеет древовидную структуру. Основная идея этого пакета состоит в том, что он осуществляет манипуляцию с именами файлов и директорий в максимально обобщённом виде, который не слишком зависит от реализации и операционной системы.
@ Файлы классифицированы как каталоги, специальные файлы и обычные файлы. Специальные файлы - рассматриваются как устройства в Windows и мягкие ссылки в Unix; они не могут быть созданы или читаться предопределенными Ада - пакетами ввода - вывода.
@ Файлы и каталоги идентифицированы строками обычным способом. Интерпретация - определяется реализацией.
@ Полное имя файла - представляет собой строку вида:
|
@ где простое имя - "library.doc". По крайней мере это выглядело так в старом добром DOS-е. В Windows XP это - может быть как:
|
@ Ради иллюстрации рассмотрим простой пример DOS. Пусть текущий каталог установлен командой "cd":
|
@ тогда функция Current_Directory выдаст строку "c:\adastuff". Процедура Set_Directory устанавливает текущий каталог. Процедуры Create_Directory и Delete_Directory создают и удаляют единственный каталог. Мы можем или дать полное имя или только часть, начинающуюся с текущего значения по умолчанию. Следующая последовательность операторов:
|
@ сначала создаст каталог, затем удалит его.
@ Процедура Create_Path создает несколько вложенных каталогов по мере необходимости. Если мы напишем:
|
@ сначала создастся каталог "books" в "c:\adastuff" а затем каталог "old" в "books". С другой стороны, если мы напишем Create_Path ("c:\adastuff\rat"); тогда никакой реакции не будет, так как путь уже существует. Процедура Delete_Tree удаляет целое дерево, включая подкаталоги и файлы.
@ Процедуры Delete_File, Rename, и Copy_File ведут себя как и ожидается из названия. Отметим особенность процедуры Copy_File которая может использоваться для копирования любого файла который может быть скопирован, использованием нормального пакет ввода - вывода, такого как Text_IO. Например, весьма утомительно использовать Text_IO для копирования файла с сохранением всех символов редактирования строк и терминаторов страницы. Это - тривиальный вопрос при использовании функции Copy_File.
@ Отметим также, что у процедур Create_Directory, Create_Path и Copy_File есть дополнительный параметр Form. Как и подобные параметры в предопределенных пакетах ввода - вывода это значение определяется реализацией.
@ Следующая группа из шести функций Full_Name, Simple_Name, Containing_Directory, Extension, Base_Name и Compose выполняют манипуляции со строками представляющими имена файлов и ни в коей мере не взаимодействуют с фактической файловой системой. И только поведение функции Full_Name зависит от текущего каталога.
@ Функция Full_Name возвращает полное имя файла. Т.е. если у нас текущий каталог все еще "c:\adastuff" то функция Full_Name ("rat\library.doc") возвратит строку "c:\adastuff\rat\library.doc", а вызов Full_Name ("library.doc") возвратит "c:\adastuff\library.doc". Факт, что такой файл не существует хоть и является несоответствием, но если имя задано синтаксически правильно то никаких исключительных ситуаций не возникает. Если же имя неправильное (например такое "66 ## 77") то соответствующее полное имя не имеет смысла, в этом случае возбуждается исключение Name_Error.
@ С другой стороны вызов Simple_Name ("c:\adastuff\rat\library.doc") возвращает "library.doc" а не "rat\library.doc". Мы можем также применить Simple_Name к строке, которая не начинается с корня. Таким образом, вызов Simple_Name ("rat\library.doc"); разрешен и также возвращает "library.doc".
@ Функция Containing_Directory_Name удаляет простую именную часть из параметра. Мы можем даже написать:
|
@ в результате получим "..\rat"; при этом будет также удалён разделитель "\".
@ Функции Extension и Base_Name возвращают соответствующие части имени файла таким образом:
|
@ Обратите внимание, что они могут быть применены к простому или к полному имени или, как здесь, на полпути между.
@ Функция Compose может использоваться для соединения различных частей имени файла:
|
@ в результате получим "rat\library.doc". Заданные по умолчанию параметры позволяют некоторым частям быть опущенными. Фактически, если третий параметр опущен тогда, второй параметр обрабатывается как простое а не базовое имя.
@ Таким образом, мы могли бы также написать:
|
@ Следующая группа функций Exists, Kind, Size и Modification_Time работают с именем файла (которое является именем реального существующего файла) и возвращают очевидный из названия результат. (Размер измеряется в потоковых элементах - обычно это байты). Различные типы и подпрограммы предоставлены для поддержки поиска в структуре каталогов для объектов с соответствующими свойствами. Это может быть сделано двумя способами, через цикл под прямым управлением программиста (иногда назваемый активной итерацией) или через доступ к параметру подпрограммы (часто назваемый пассивной итерацией). Сначала рассмотрим способ с активной итерацией.
@ Процедуры Start_Search, End_Search, Get_Next_Entry и функция More_Entries управляют циклом поиска. Общая схема такая:
|
@ Здесь используются три типа. Тип Directory_Entry_Type является ограниченым частным типом и действует как своего рода маркер к найденным входам. Действительное значение этого типа может быть создано только вызовом процедуры Get_Next_Entry, второй параметр Directory_Entry_Type - параметр типа in. Тип Search_Type также является ограниченным частным типом и содержит состояние поиска. Тип Filter_Type обеспечивает простое средство идентификации вида файла, который будет найден. Он имеет три компоненты соответствующие трем значениям File_Kind перечислимого типа, и используется процедурой Start_Search.
@ Предположим, что мы хотим искать все обычные файлы с расширением "doc" в каталоге "c:\adastuff\rat". Тогда мы можем написать:
|
@ Третий параметр Start_Search (значение которого "*.doc" в вышеупомянутом примере) представляет собой шаблон для поиска. Её интерпретация определяется реализацией за исключением того, что пустая строка означает соответствие всему. Однако, мы ожидали бы, что написание "*.doc" будет означать поиск только файлов с расширением "doc".
@ Альтернативный механизм использующий пассивную итерацию такой. Сначала мы объявляем подпрограмму следующего вида:
|
@ после чего объявляем фильтр и вызываем процедуру Search следующим образом:
|
@ Параметры процедуры Search такие же что и у Start_Search за исключением того, что первый параметр типа Search_Type опущен а последний параметр, который идентифицирует процедуру Do_It добавлен.
@ Переменная Item, которую мы объявили в активной итерации, является теперь параметром Item процедуры Do_It.
@ У каждого подхода есть свои преимущества. При пассивной итерации мы не можем сделать ошибку забыв вызвать End_Search. Но некоторые находят, что активная итерация проще для понимания и может быть легко использована для параллельных поисков.
@ Последняя группа функций позволяет нам сделать полезные вещи с результатами нашего поиска. Таким образом, Simple_Name и Full_Name преобразовывают значение Directory_Entry_Type соответственно в простое или полное имя файла. Получив имя файла, мы можем сделать все что мы хотим, но для удобства предоставлены функции Kind, Size и Modification_Time которые непосредственно берут параметр Directory_Entry_Type.
@ Завершая этот пример мы можем распечатать таблицу найденных файлов, печатая их простое имя, размер и время модификации. Используя активный подход мы можем написать:
|
@ В результате получим нечто такое:
|
@ Отметим использование функции Image из пакета Ada.Calendar.Formatting обсужденного в предыдущей секции.
@ Обратите внимание, что поиск выполняется только в текущем каталоге без подкаталогов. Если же мы хотим рассматривать и подкаталоги тогда, мы можем использовать функцию Kind, чтобы идентифицировать подкаталоги и затем искать рекурсивно.
@ Нужно подчеркнуть что пакет Ada.Directories сильно зависит от реализации и в действительности может вообще не поддерживаться некоторыми реализациями вообще. Реализациям советуют обеспечить любые дополнительные полезные функции относительно получения другой информации о файлах (таких как имя владельца или оригинальной даты создания) в дочернем пакете Ada.Directories.Information.
@ В заключении отметим, что неправильное употребление различных операций возбуждает одно из исключений Status_Error, Name_Error, Use_Error или Device_Error из пакета IO_Exceptions.
2010-10-24 00:26:58
. .