Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

CGI-программирование с самого начала


Уважаемые подписчики!

После некоторого вынужденного перерыва мы вновь продолжаем нашу рассылку. Если Вы подписались на нее недавно, то мы рекомендуем Вам прочесть также и предыдущие выпуски. Их Вы сможете найти в архиве рассылки.

Работа с файлами в CGI-скриптах на Perl

Практически все CGI-скрипты используют те или иные внешние файлы в своей работе: счетчики посетителей, например, хранят во внешних файлах значение счетчика и другую служебную информацию, скрипты гостевой книги - содержимое книги и т.д.

Язык Perl обладает мощными и разнообразными средствами для работы с файлами. При этом, как всегда, разработчики языка Perl постарались, чтобы мощность и универсальность средств языка сочеталась с простотой и понятностью их использования.

В этом выпуске мы рассмотрим основные понятия, связанные с работой с файлами, научимся открывать и закрывать файлы, а также читать и записывать в них текстовые данные.

Как и в других языках программирования, в языке Perl работа с файлом обычно состоит из нескольких "этапов": открытие файла, собственно чтение или запись (обмен данными) и закрытие файла.

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

Как правило, обмен с открытыми файлами (чтение из файла и запись в файл) осуществляется через так называемый дескриптор файла - особый указатель, который "связывается" с файлом при его открытии. В Perl дескриптор файла представляет собой комбинацию английских букв и цифр. Считается хорошим тоном использовать в дескрипторах заглавные английские буквы.

Поскольку одновременно может быть открыто несколько файлов, дескриптор файла однозначно определяет конкретный открытый файл и режим обмена с ним. У одновременно открытых файлов должны быть различные дескрипторы.

Существует три "предопределенных" дескриптора, которые соответствуют стандартным потокам ввода-вывода скрипта:

STDOUT - стандартный поток вывода
STDIN - стандартный поток ввода
STDERR - стандартный поток ошибок

Эти "файлы" изначально открыты, и Вы можете работать с ними, как и с другими файлами с последовательным доступом.

Открытие файла. Функция open.

Одним из принципов разработчиков языка Perl был принцип "существует несколько путей сделать то, что Вы хотите". Это в полной мере относится и к работе с файлами. В Perl фактически даже существует несколько наборов команд для открытия файлов и обмена с ними!

В этом выпуске мы рассмотрим наиболее "штатный", гибкий и универсальный инструмент открытия файла - функцию open.

Функция open имеет несколько форматов. Чаще всего применяется формат с двумя аргументами:

open ДЕСКРИПТОР, СТРОКА

где ДЕСКРИПТОР - это дескриптор открываемого файла; если на момент открытия файла данный дескриптор уже соответствовал открытому файлу, то предыдущий открытый файл будет закрыт; СТРОКА - строка, определяющая имя файла и режим работы с ним.

Параметр СТРОКА в общем случае "имитирует" элементы синтаксиса командной строки UNIX shell (очень похож на синтаксис командной строки MS DOS), со многими ее возможностями.

При открытии файлов в качестве параметра СТРОКА указывается имя файла (путь к файлу), которое может предваряться префиксами, обозначающими желаемый режим доступа к файлу. Наиболее часто используются слкдующие префиксы:

< - чтение;
> - запись;
>> - добавление в конец файла.

По умолчанию (при отсутствии префикса) подразумевается открытие файла на чтение ('<').

Примеры:


open FILE1,"<data.txt";        #Открыть файл data.txt на чтение
open FILE1,"data.txt";         #То же
open U1,">counter.txt";        #Открыть data.txt на запись
open LOG,">>mylog.txt";        #Открыть mylog.txt для добавления

Параметр СТРОКА также может быть опущен, в этом случае значение этого параметра берется из скалярной переменной с именем УКАЗАТЕЛЬ. Это - формат open с одним аргументом:


$TEXT="file.txt";
open TEXT;                     #Открыть для чтения файл file.txt

Кроме вышеуказанных форматов функции open (с одним и двумя аргументами), существует еще один ее формат - с тремя аргументами:

open УКАЗАТЕЛЬ, РЕЖИМ, ИМЯ

В этом случае префикс режима и имя файла указываются не в одном параметре, а в двух различных:


open FILE1,"<","data.txt";        #Открыть файл data.txt на чтение

В случае успешного открытия файла функция open "связывает" файл с дескриптором и возвращает "истину". После успешного открытия файла можно вести обмен данными с ним в выбранном режиме, используя этот дескриптор.

В случае ошибки открытия файла функция open возвращает "ложь" и указывает в зарезервированной переменной $! причину ошибки.

При открытии существующего файла на запись (режим '>') существующее содержимое файла будет удалено и заменено новыми записываемыми данными, а при открытии для добавления в конец файла (режим '>>') "старое" содержимое файла не удаляется, а новые записываемые данные будут дописаны в конец файла. Этот режим очень удобен для ведения различных журналов, логов и т.п.

При открытии несуществующего файла на запись (режимы '>' и '>>') будет создан файл с нужным именем. При открытии несуществующего файла на чтение ('<') произойдет ошибка открытия (функция open вернет "ложь").

Обмен данными с файлом

После успешного открытия файла мы можем производить чтение из него и/или запись в него - в зависимости от выбранного режима.

Рассмотрим чтение и запись текстовых данных.

Чтение из файла удобно осуществлять с помощью оператора <ДЕСКРИПТОР> (дескриптор файла в угловых скобках).

В скалярном контексте этот оператор возвращает очередную строку из файла (вместе с символами конца строки, специфическими для используемой операционной системы, если они есть в конце строки) или "неопределено" в случае ошибки чтения или при достижении конца файла (если строк для чтения больше нет).

В списковом контексте возвращается список всех строк файла.

Пример 1:

 open FILE1, "<data.txt";
 $line=<FILE1>;
 close FILE1;

Пример 2:
 open FILE1, "<data.txt";
 @lines=<FILE1>;
 close FILE1;

В примере 1 в переменную $line будет прочитана первая строка файла data.txt, а в примере 2 - в массив @lines будут помещены все строки из этого файла.

Вывод в файл текста обычно производится с помощью функции print, с которой мы уже знакомы. Эта функция позволяет осуществлять вывод в любой файл, для этого первым ее параметром должен быть дескриптор файла.

print FILE "line1\n";
print FILE "line2\n";
print FILE "line3\n";

Обратите внимание, что между дескриптором файла и выводимыми данными должен быть пробел, а не запятая.

Если дескриптор файла опущен (та самая форма функции print, которую мы обычно применяли до сих пор), то в качестве файла для вывода используется текущий выбранный дескриптор. Изначально (при запуске скрипта) текущим выбранным дескриптором является, как Вы уже, наверное, догадались, STDOUT :-)

Выбор текущего дескриптора для вывода осуществляется с помощью функции select:

select ДЕСКРИПТОР

Обращаю ваше внимание на то, что в Perl функция print выводит в файл то, что указал программист, и ничего больше - в отличие, скажем, от оператора PRINT языка BASIC, который по умолчанию заканчивает вывод символами конца строки. Поэтому следующий фрагмент:

print FILE "line1";
print FILE "line2";
print FILE "line3";

выведет в файл не три строчки, а одну: "line1line2line3".

Поэтому символы концы строк следует указывать явно.

Конечно же, существуют и другие функции для обмена данными с файлом. Их мы рассмотрим в следующих ближайших выпусках рассылки.

Закрытие файла

После завершения обмена с файлом его необходимо закрыть. Делается это функцией close:

close ДЕСКРИТПОР

Кроме того, все незакрытые файлы автоматически закрываются при завершении работы скрипта. Это была хорошая идея, т.к. программист вполне может забыть закрыть файл явно. Хотя это, мягко говоря, не считается профессиональным подходом :-)

Файлы в UNIX

Поскольку подавляющее большинство серверов хостинга работает на базе ОС UNIX и ее разновидностей (FreeBSD, Linux, Solaris и др.), то при разработке CGI-скриптов важно знать особенности файловой системы этих ОС.

Самая "внешняя" особенность файловой системы UNIX заключается в том, что заглавные и строчные буквы в именах файлов считаются различными символами. Так, для Windows файлы data.txt, Data.txt и DATA.TXT имеют одинаковое имя, а для UNIX это - совершенно разные файлы. Это, кстати, достаточно распространенная ошибка вообще у начинающих веб-мастеров, закачивающих файлы на сайт и затем получающих ошибку '404 Not Found', несмотря на то, что на локальном компьютере (под Windows) все ссылки прекрасно работали. :-)

Еще одна внешняя особенность - в UNIX для разделения подкаталогов используются символы не обратной косой черты '\', как в Windows, а прямой '/'.

Еще одна особенность заключается в развитой системе так называемой "локальной защиты" файлов. Поскольку UNIX изначально была "серьезной" сетевой многопользовательской системой, она имеет развитую систему ограничений доступа к файлам, позволяющую "оградить" файлы одного пользователя от деструктивных действий (или просто нездорового любопытства :-) ) другого. Поэтому, скажем, ошибки открытия файла могут быть связаны не только с отсутствием файла, но и отсутствием у Perl-скрипта нужных прав доступа к данному файлу. Более подробно атрибуты доступа к файлам и работу с ними в Perl-скриптах мы рассмотрим в одном из ближайших выпусков рассылки.

На сегодня все. Мы рассмотрели основы работы с файлами, так сказать, "вершину айсберга" :-) В следующих выпусках мы продолжим тему работы с файлами - нас ждет еще много чего интересного. До следующих выпусков :-)

Успехов!


Андрей
angel07@inbox.ru

В избранное