с этого урока мы будем
Урок 13. Функции работы с файлами Собственно, начиная с этого урока мы будем изучать встроенные в Perl функции (до этого мы изучали операторы), и начнем с функций, которые позволяют нам работать с файлами. Дескриптор файла Дескриптор файла в Perl-программе — это имя соединения для ввода-вывода между вашим Perl-процессом и внешним миром. Имена дескрипторов файлов похожи на имена помеченных блоков, но они берутся из другого пространства имен (поэтому у вас может быть скаляр $fred, массив $fred, хеш %fred, метка fred, а теперь и дескриптор файла fred). Как и метки блоков, дескрипторы файлов используются без специального префиксного символа, поэтому их можно спутать с существующими или возможными в будущем зарезервированными словами (для команд, подпрограмм и др.). Рекомендую составлять дескрипторы файлов только из прописных букв. Во-первых, они будут хорошо выделяться в тексте программы, и, во-вторых, благодаря этому программа не даст сбой при введении нового зарезервированного слова. Открытие и закрытие дескриптора файла open (FileVar, FileName); close (FileVar); Функция Open открывает указанный файл и ассоциирует с ним файловую переменную (дескриптор файла). В зависимости от спецсимвола, стоящего перед именем файла, файл можно открыть с разным способом доступа к нему. |
open (FV,"FN"); | Файл открыт для чтения. Запись в него запрещена. |
open (FV,">FN"); | Файл открыт для записи. Когда файл открыт таким способом, его содержимое автоматически стирается (а если файл не существует - создается) и в файл можно добавлять данные. |
open (FV,">>FN"); | Файл открыт для записи в конец. При таком способе открытия файла, тело файла не изменяется и разрешено добавлять строки в его конец. |
open (FV,"+<FN"); | Файл открыт для чтения и записи. |
open (FV,"|FN"); | Направить информацию на вход программы. |
open (FV,"FN|"); | Считать информацию с выхода программы. |
open (FV,"|FN|"); | И то и другое. |
Из файла можно считать данные в виде массива и построчно. При считывании файла построчно, какой-то переменной, при первом считывании, присваивается первая строка файла и указатель перемещается на следующую строку. Такое присваивание возвращает True. При втором считывании присваивается вторая строка, при третьем - третья и т.д. до конца файла. Когда указатель дойдет до последней строки, счетчик сбрасывается, указатель перемещается на первую строчку файла, а возвращаемое выражение становится равным False
При считывании файла в массив, каждая строка файла помещается в отдельную ячейку массива. Плюсы и минусы этих методов очевидны: При считывании файла построчно, экономится память сервера, но работать с файлом становится неудобно, да и этот метод не очень производителен. Другое дело - работа с массивом: это быстро, это удобно, но есть очевидный минус - сильная загрузка памяти сервера. Но несмотря на это, данный метод пользуется огромной популярностью при написании небольших скриптов.
Чтобы считать файл/строку в какую-то переменную, этой переменной присваивают дескриптор файла, заключенный в треугольные скобки:
@array = <FileVar>; $Var = <FileVar>;
Чтобы закрыть файл, используют функцию Close. Хотя её использование не обязательно, т.к. файл закроется сам после окончания выполнения скрипта, но желательно и является признаком хорошего стиля программирования.
Запись в тело файла
Нетрудно догадаться, что работать с файлом (считывать и записывать информацию) можно только тогда, когда он открыт.
Выводятся данные в файл всё тем же оператором Print. Оператору необходимо указать, в какой именно файл (может быть несколько одновременно открытых файлов) следует выводить информацию, затем помещают выражение, предназначенное для вывода:
open (file,">>file.txt"); print file "Здесь был Вася"; close file;
Если не указать файловую переменную, строка "Здесь был Вася" выведется на экран браузера.
Путь к файлу
Если опустить путь к файлу, а указать только его имя, будет считаться, что указанный файл лежит в той же директории, что и файл скрипта. Допускается указывать как абсолютный, так и относительный путь. К примеру, имеем такое дерево файлов и каталогов:
D:/USR/LOCAL/APACHE |----> CGI-BIN | |----> MYDIR | | |----> file0.txt | | | |----> script.pl | |----> file1.txt | |----> HTDOCS |----> file2.txt
Тогда абсолютные пути к файлам будем иметь такими:
D:/USR/LOCAL/APACHE/CGI-BIN/MYDIR/file0.txt D:/USR/LOCAL/APACHE/CGI-BIN/file1.txt D:/USR/LOCAL/APACHE/CGI-BIN/script.pl D:/USR/LOCAL/APACHE/HTDOCS/file3.txt
А относительно файла script.pl, пути будут такими:
MYDIR/file0.txt file1.txt ../HTDOCS/file2.txt
При написании CGI программ принято использовать относительные пути, т.к. владельцы WEB-серверов часто скрывают абсолютное расположение своих директорий.
Блокировка файла, функция Flock
flock(FileVar, operation);
Сразу сделаю небольшую оговорочку, эта функция работает ТОЛЬКО под Unix-подобными операционными системами (Unix, Linux, FreeBSD, SunOS и др.) и Windows NT, W2k, XP...
Необходимость блокировки файлов возникает очень часто когда ваша Perl программа использует данные непосредственно из файлов. Это может быть гостевая книга, форум, чат, счетчик и т. д.
Сначала кажется, что никаких проблем не будет если просто написать код, открывающий файл при необходимости и закрывающий его, после завершения операции чтения/записи:
open(file, "file.txt"); while($string=<file>){ print $string; } close(file);
Если использовать такой код при создании, к примеру, гостевой книги, то существует вероятность, при которой один пользователь добавляет запись, а другой просматривает записи в одно и то же время. Таким образом одновременно два процесса в одно и то же время пытаются выполнить операцию ввода/вывода (в/в) с файлом. Это может привести к серьезным ошибкам, вплоть до потери данных. Для того, чтобы избежать таких ситуаций, необходимо блокировать файл непосредственно перед выполнением операции в/в. В Perl'e есть специальная функция для блокировки файлов, которая используют системные вызовы.
В качестве параметра operation допускаются следующие значения:
"LOCK_SH" или "1" | Блокировка для чтения |
"LOCK_EX" или "2" | Блокировка для записи |
"4" | "двухстороннее" блокирование |
"LOCK_UN" или "8" | Разблокирование |
Используя эту функцию, можно обезопасить свою программу от ошибки ввода/вывода. Код чтения данных из файла с использованием блокировки может выглядеть так:
open(file, "file.txt"); flock(file, LOCK_SH); while($string=<file>){ print $string; } close(file);
Примечание: Не обязательно файл разблокировывать, т.к. при закрытии файловой переменной, Perl сделает это автоматически.
Код записи данных в файл, с блокировкой:
open (FH, ">>data.tmp"); flock(FH, 2); $str="new line"; print FH $str; flock(FH, 8); close(FH);
Есть одна особенность при использовании блокировки файлов: если к файлу может обратиться хотя бы один процесс, в котором не ставится блокировка, то вся система блокирования становится бесполезной. Другими словами, надо использовать блокировку не только при создании/обновлении/записи в нужный файл, но и в других скриптах, работающих с этими файлом.
* * * *
Напишем скрипт, который записывает в файл переданную ему строчку, и удаляет строку с переданным номером:
#!/usr/bin/perl # programm 13 print "Content-type: text/html\n\n";
&parse_form;
Добавить запись | ||
Удалить запись номер: |
if ($FORM{'action'} eq "add") { # выполняем этот блок когда хотим записать в файл open(file,">>file.txt"); print file "$FORM{'string'}\n"; close file; open(file,"file.txt"); @array=; close file; foreach $i(@array){ $u++; print "$u. $i
"; } } elsif ($FORM{'action'} eq "del") { # выполняем этот блок когда хотим удалить строку open(file,"file.txt"); @array=; close file; open(file,">file.txt"); $size=@array; for($i=0;$i; close file; foreach $i(@array){ $u++; print "$u. $i
"; } } else { # вып. этот код когда хотим просмотреть все записи open(file,"file.txt"); @array=; close file; foreach $i(@array){ $u++; print "$u. $i
"; } }
Возможно, Вам будет трудно поначалу разобраться с работой этой программы. Попробуйте мысленно "запустить" её, представив что Вы - это Perl. Последовательно интерпретируйте код, возможно записывая часть результатов на бумагу. Мысленно подставляйте значения в форму и снова "запускайте" её, тогда Вы быстро поймете работу программы. Важно обладать таким навыком, это впредь поможет Вам находить ошибки в своих и чужих скриптах.
* * * *
Напишите программу, которая создает в директории с HTML документами, HTML файл, в котором записана таблица Пифагора. Откройте этот файл через его URL. Всё ли правильно отображается?
Дополнительный материал: [работа с файлами] [работа с файлами 2] [работа с файлами 3]
[Содержание] [Вступление] [необходимое для начала изучения] [урок 1] [урок 2] [урок 3] [урок 4] [урок 5] [урок 6] [урок 7] [урок 8] [урок 9] [урок 10] [урок 11] [урок 12] [урок 13] [урок 14] [урок 15] [урок 16] [урок 17] [урок 18] [урок 19] [урок 20] [урок 21] [урок 22] [урок 23] [урок 24] [урок 25] [урок 26] [урок 27] [урок 28] [правила хорошего тона] [приложение A] [приложение Б] [приложение В] [заключение] [благодарности]
Copyright (c) ClericICN, 2002