07 апреля 2020

Дескрипторы файлов

    Когда в программе мы создаем переменные и храним в них разнообразные данные, мы теряем их по завершении работы программы. Если нам необходимо сохранить данные и использовать их в разрабатываемых программах, мы создаем файл, записываем в него данные и сохраняем его на диске. Практически любой язык программирования предоставляет программисту средства манипулирования файлами и хранимыми в них данными.
     Доступ к файлам в программе Perl осуществляется через специально создаваемые дескрипторы, которые можно рассматривать как некоторый особый вид переменных. Один дескриптор в каждый момент времени может быть связан с одним и только одним файлом, хотя на протяжении всей программы один и тот же дескриптор можно последовательно связывать с разными файлами.
     Более того, дескриптор можно связать не только с файлом, но и с программным каналом, обеспечивающим связь между процессами. В этой главе мы не будем касаться вопросов взаимодействия программ с другими процессами, а рассмотрим только работу с файлами и их содержимым. Поэтому дескрипторы мы иногда будем называть дескрипторами файлов.
     Дескриптор — это символическое имя, которое используется в программе Perl для представления файла, устройства, сокета или программного канала. При создании дескриптора он "присоединяется" к соответствующему объекту данных и представляет его в операциях ввода/вывода. Мы дали наиболее полное определение дескриптора, чтобы читатель понимал, что дескриптор позволяет работать не только с данными файлов, но и с данными других специальных программных объектов, реализующих специфические задачи получения и передачи данных. Когда дескриптор присоединен к файлу, мы будем называть его дескриптором файла.
Замечание
При открытии файла в системе UNIX ему также назначается файловый деск-, риптор, или дескриптор файла, который ничего общего не имеет с файловым дескриптором Perl. В UNIX дескриптор файла является целым числом, тогда как в Perl это символическое имя, по которому мы можем ссылаться на файл. Чтобы получить числовой файловый дескриптор в программе Perl, можно воспользоваться функцией f ileno ().
     В программе дескриптор файла чаще всего создается при открытии файла функцией open (), которой передаются два параметра — имя дескриптора и строка с именем файла и режимом доступа:
open( LOGFILE, "> /temp/logfile.log");
     Этот оператор создает дескриптор с именем LOGFILE и присоединяет его к файлу с указанным именем, который открывается в режиме записи (строка второго параметра начинается с символа ">"). В этом разделе мы не будем касаться вопросов, связанных с режимом открытия файла, а сконцентрируем наше внимание на дескрипторах. В следующем разделе режимы открытия файла будут рассмотрены нами подробнее.
     Дескриптор, как указывалось, является символическим именем файла и представляет собой правильный идентификатор, который не может совпадать с зарезервированными словами Perl. В нашем примере создается дескриптор LOGFILE, "замещающий" в операциях ввода/вывода файл, к которому он присоединен (/temp/logfile.log). Например, известной нам функцией print о мы можем теперь записать в этот файл значение какой-либо переменной:
print LOGFILE $var;
      Любой созданный дескриптор попадает в символьную таблицу имен Perl, в которой находятся также имена всех переменных и функций. Однако дескриптор не является переменной, хотя некоторые авторы и называют его файловой переменной. В имени дескриптора не содержится никакого префикса, присущего переменным Perl ($, @ или %). Поэтому его нельзя непосредственно использовать в операции присваивания и сохранить в переменной или передать в качестве параметра в функцию. Для подобных целей приходится использовать перед его именем префикс *, который дает ссылку на глобальный тип данных. Например, предыдущий оператор печати в файл, определенный дескриптором LOGFILE, можно осуществить с помощью следующих операторов, предварительно сохранив ссылку на дескриптор в переменной $iogf:
$logf = *LOGFILE; print $logf $var;
     В операции print первая переменная $iogf замещает дескриптор файла LOGFILE, в который выводится значение второй переменной $var.
Замечание
В программах Perl принято в именах дескрипторов использовать прописные буквы. Подобная практика позволяет легко обнаруживать их в программе и не приводит к конфликтам с зарезервированными именами функций, которые обычно определены строчными буквами.
     В любой программе Perl всегда существуют три предопределенные дескриптора (STDIN, STDOUT и STDERR), которые связаны со стандартными устройствами ввода/вывода и используются некоторыми функциями Perl в качестве умалчиваемых дескрипторов файлов ввода или вывода. Как мы уже знаем, дескриптор STDIN связан со стандартным устройством ввода (обычно клавиатура), STDOUT и STDERR — со стандартным устройством вывода (обычно экран монитора). Стандартное устройство ввода используется операцией о, если в командной строке вызова сценария Perl не задан список файлов. Дескриптор STDOUT ПО УМОЛЧАНИЮ ИСПОЛЬЗУЕТСЯ ФУНКЦИЯМИ print И die, а STDERR — функцией warn. Другие функции также используют предопределенные дескрипторы файлов для вывода своей информации.
     При вызове программ в среде Unix и DOS можно перенаправлять стандартный ввод и вывод в другие файлы, задавая в командной строке их имена с префиксами > для файла вывода и < для файла ввода:
peri program.pl <in.dat >out.dat
     При выполнении программы program.pi все исходные данные должны быть подготовлены в файле in.dat. Вывод будет сохранен в файле out.dat, а не отображаться на экране монитора.
     Перенаправление стандартного ввода и вывода, а также стандартного отображения ошибок, можно осуществлять непосредственно в программе Perl. Для этого следует функцией ореп() связать соответствующий предопределенный дескриптор с некоторым дисковым файлом:
open(STDIN, "in.dat"); open(STDOUT, ">out.dat"); open(STDERR, ">err.dat");
     Теперь весь стандартный ввод/вывод будет осуществляться через указанные в операторах open о файлы. Обратите внимание, что при переопределении стандартных файлов вывода и ошибок перед именами файлов стоит префикс ">", указывающий на то, что файлы открываются в режиме записи.
Замечание
Перенаправление стандартного ввода/вывода в программе можно производить только один раз. Это переназначение действует с момента перенаправления ввода/вывода и до конца программы, причем функцией open () нельзя вернуть первоначальные установки для дескрипторов STDIN, STDOUT и STDERR.