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

Любая программа, написанная на любом языке программирования, обычно получает из внешней среды и посылает в нее информацию. Все языки программирования предоставляют средства для ввода данных в программу и вывода данных из нее. В Perl определено несколько способов получения программой данных извне и вывода информации из выполняющегося сценария.
Так как язык Perl — это язык управления процессом, то, естественно, в нем упрощено общение с операционной системой — достаточно заключить в сценарии ее команду в обратные кавычки (или выполнить эквивалентную операцию qx{}), и результаты выполнения команды операционной системы становятся доступны в программе Perl.
Чаще всего при взаимодействии с внешней средой используются файлы. Прочитать данные из внешнего файла или группы файлов, записать результаты вычислений во внешний файл или отобразить их на экране монитора — все эти действия реализуются разнообразными операциями и функциями языка Perl.
Для чтения из файла или стандартного устройства ввода (обычно это клавиатура) используется операция «ромб» (<>), которой в качестве операнда передается дескриптор файла, а в случае ввода данных с клавиатуры — либо никакого операнда, либо предопределенный дескриптор файла STDIN, связанный со стандартным устройством ввода. Для записи информации в файл или передачи на стандартное устройство вывода (обычно это экран монитора) можно использовать функцию print или специальные функции работы с файлами из стандартной библиотеки Perl, которая автоматически подключается при выполнении сценария интерпретатором.
До начала работы с файлом в программе он должен быть открыт, а после завершения работы с ним закрыт специальными функциями из стандартной библиотеки. При открытии файла с ним связывается специальный дескриптор, который в дальнейшем и используется в функциях работы с файлами для ссылки на этот файл. Так как практически все общение с внешней средой из сценария Perl происходит с помощью файлов (даже ввод-вывод на стандартные устройства ввода-вывода представляется как манипуляции с предопределенными открытыми файлами, имеющими соответственно дескрипторы STDIN, STDOUT и STDERR), то наше знакомство с системой ввода-вывода в Perl мы начнем с важного понятия дескриптора файла, который можно рассматривать как некоторый особый вид переменной. Один дескриптор в каждый момент времени может быть связан с одним и только одним файлом, хотя на протяжении всей программы один и тот же дескриптор можно последовательно связывать с разными файлами.
Более того, дескриптор можно связать не только с файлом, но и с программным каналом, обеспечивающим связь между процессами. В этой главе мы не будем касаться вопросов взаимодействия программ с другими процессами, а рассмотрим только работу с файлами и их содержимым. Поэтому дескрипторы мы иногда будем называть файловыми дескрипторами, или дескрипторами файлов.

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

Дескриптор — это символическое имя, которое используется в программе Perl для представления файла, устройства, сокета или программного канала. При создании дескриптора он «присоединяется» к соответствующему объекту данных и представляет его в операциях ввода-вывода. Мы дали наиболее полное определение дескриптора, чтобы читатель понимал, что дескриптор позволяет работать не только с данными файлов, но и с данными других специальных программных объектов, используемых для реализации специфических задач получения и передачи данных. Когда дескриптор присоединен к файлу, мы будем называть его файловым дескриптором, или дескриптором файла.
ВНИМАНИЕ При открытии файла операционная система (Windows или UNIX) также назначает ему системный файловый дескриптор, который ничего общего не имеет с файловым дескриптором Perl. Системный файловый дескриптор является целым числом, тогда как в Perl это символическое имя, по которому мы можем ссылаться на файл. Чтобы получить системный числовой файловый дескриптор в программе Perl, можно воспользоваться функцией fileno( ).
В программе дескриптор файла создается при открытии файла функцией ореn( ), первым параметром которой и является имя дескриптора, тогда как остальные параметры определяют режим доступа к файлу и его имя:
open( FILE, ">", "/temp/file.txt");
Этот оператор создает дескриптор с именем FILE и присоединяет его к файлу с указанным именем, который открывается в режиме записи, определяемым вторым параметром функции open(). В этом разделе мы не будем касаться вопросов, связанных с режимом открытия файла, а сконцентрируем наше внимание на дескрипторах. В следующих разделах режимы открытия файла будут рассмотрены нами подробнее.
Дескриптор файла в программе, как отмечалось, является символическим именем файла и представляет собой правильный идентификатор, который не может совпадать с зарезервированными словами Perl. Более того, мы можем задавать его, не заключая в кавычки, так как в этом случае интерпретатор perl будет рассматривать их как простые слова и автоматически интерпретировать как строковые данные.
ПРИМЕЧАНИЕ В программах Perl принято в именах дескрипторов использовать прописные буквы. Подобная практика позволяет легко обнаруживать их в программе и не приводит к конфликтам с зарезервированными именами функций, которые обычно определены строчными буквами.
В нашем примере создается дескриптор FILE, «замещающий» в операциях ввода-вывода файл, к которому он присоединен (/temp/file.txt). Например, известной нам функцией print( ) мы можем теперь записать в этот файл значение какой-либо переменной, указав перед списком вывода дескриптор файла (запятая после дескриптора файла не нужна!):
print FILE "Переменная \$var = $var";
Любой созданный дескриптор попадает в таблицу символов, создаваемую интерпретатором perl, в которой находятся также имена всех переменных и функций. При этом для переменных разных типов, но с одинаковыми идентификаторами, например $var, @var и %var, в таблице символов создается целая запись, в которой каждому типу переменной соответствует свой элемент. Однако дескриптор Perl не является переменной (хотя иногда его и называют файловой переменной) — в имени дескриптора не содержится никакого префикса, присущего переменным Pert ($, @ или %), и поэтому его нельзя непосредственно использовать в операции присваивания, а также сохранять в какой-либо переменной или передавать в качестве параметра в функцию. Для выполнения подобных действий следует использовать внутренний тип данных Perl — тип typeglob, который позволяет получить ссылку на запись таблицы символов, соответствующую определенному идентификатору. Для этого достаточно перед идентификатором поставить префикс *. Доступ к элементам записи (ссылкам на переменные соответствующего типа данных) производится с помощью специальной конструкции *Идентификатор{ключ}, в которой ключ соответствует заданному типу:
$scalarref = *s{SCALAR}; # Ссылка на скалярную переменную
$arrayref  = *s{ARRAY};  # Ссылка на массив скаляров
$hashref   = *s{HASH};   # Ссылка на ассоциативный массив
$coderef   = *s{CODE};   # Ссылка на подпрограмму
$ioref     = *s{IO};     # Ссылка на дескриптор файла
$globref   = *s{GLOB};   # Ссылка на все запись
Последняя конструкция эквивалентна $globref = *s.
Если при обращении к функции требуется передать идентификатор файла, то можно использовать ссылку на всю запись таблицы символов, соответствующую имени идентификатора, используемого для дескриптора файла. Например, печать в файл, открытый с дескриптором FILE, можно осуществить с помощью следующих операторов, предварительно сохранив ссылку на тип typeglob в переменной $file:
$file = *FILE; 
print $file $var;
Здесь в операции print первая переменная $file замещает дескриптор файла, в который выводится значение переменной $var. Мы бегло познакомили читателя со ссылками на глобальные имена в связи с дескрипторами файлов.
В любой программе Perl определены три дескриптора — STDIN, STDOUT и STDERR, — которые связаны со стандартными устройствами ввода-вывода и используются некоторыми функциями Perl в качестве дескрипторов файлов ввода или вывода по умолчанию. Дескриптор STDIN связан со стандартным устройством ввода (обычно клавиатура), STDOUT и STDERR — со стандартным устройством вывода (обычно экран монитора). Стандартное устройство ввода используется в операции ввода <> без операнда, если в командной строке вызова сценария Perl не задан список файлов. Дескриптор STDOUT связан со стандартным устройством вывода и по умолчанию используется, например, функциями print и die, a STDERR представляет файл, связанный также со стандартным устройством вывода, в который обычно выводятся различные ошибки и предупреждения как интерпретатора, так и некоторых стандартных функций, например warn.
При вызове программы в среде UNIX и DOS, а также из командной строки Windows можно переназначить для этой программы используемые в ней стандартные устройства ввода и вывода таким образом, чтобы они соответствовали некоторым файлам. Для этого в командной строке вызова программы следует после всех передаваемых ей параметров (если это необходимо) задать имена файлов с префиксами < (для файла ввода) и > (для файла вывода):
perl program.pl <in.dat >out.dat
При выполнении программы program.pl все исходные данные должны быть подготовлены в файле in.dat. Вывод будет осуществляться в файл out.dat, а не на экран монитора.
Переназначение устройств стандартного ввода и вывода, а также стандартного устройства отображения ошибок можно осуществлять непосредственно в программе Perl. Для этого следует функцией open( ) связать соответствующий предопределенный дескриптор с некоторым дисковым файлом:
open(STDIN,  "in.dat");
open(STDOUT, ">out.dat");
open(STOERR, ">err.dat");
Теперь весь стандартный ввод-вывод будет осуществляться через указанные в операторах open( ) файлы. Обратите внимание, что при переопределении стандартных файлов вывода и ошибок перед именами файлов стоит префикс >, указывающий на то, что файлы открываются в режиме записи.
ПРИМЕЧАНИЕ Переназначение стандартного ввода-вывода в программе можно производить только один раз. Оно действует с момента переназначения стандартных устройств ввода-вывода и до завершения выполнения программы, причем функцией ореn( ) нельзя вернуть первоначальные установки для дескрипторов STDIN, STDOUT и STDERR.

Следующая страница Содержание главы


Реклама