Perl как считать данные из текстового файла. Файловый ввод и вывод

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

Полный перечень унарных операций проверки файлов

R Файл может читаться эффективным uid/gid -w Записывать в файл может эффективный uid/gid -x Файл может выполняться эффективным uid/gid -o Владельцем файла является эффективный uid/gid -R Файл может читаться действительным uid/gid -W Записывать в файл может действительный uid/gid -X Файл может выполняться действительным uid/gid -O Владельцем файла является действительный uid/gid -e Файл существует -z Размер файла равен нулю -s Размер файла отличен от нуля (возвращает размер) -f Файл является обычным (plain) файлом -d Файл является каталогом -l Файл является символической ссылкой -p Файл является именованным програмным каналом (FIFO) или проверяемый дескриптор связан с програмным каналом -S Файл является сокетом -b Файл является специальным блочным файлом -c Файл является специальным символьным файлом -t Дескриптор файла связан с терминалом -u У файла установлен бит setuid -g У файла установлен бит setgid -k У файла установлен бит запрета (sticky bit) -T Файл является текстовым файлом -B Файл является двоичным (противоположным текстовому) -M Возраст файла в днях на момент выполнения программы -A То же для врмени последнего обращения к файлу -C То же для время последней модификации индексного дескриптора файла

Унарные операции применяются к строке, содержащей имя файла, к выражению, вычисляемым значением которого является имя файла, или к файловому дескриптору Perl. Если параметр операции не задан, то она тестирует файл, чье имя содержится в специальной переменной $_. Каждая операция проверки атрибута файла возвращает 1, если файл обладает соответствующим атрибутом, пустую строку "" в противном случае и неопределенное значение undef, если указанный в параметре файл не существует.

Несколько слов об алгоритме определения текстовых и двоичных файлов (операции -T и -B). Эти операции анализируют содержимое первого блока файла на наличие "странных" символов - необычных управляющих последовательностей или байтов с установленными старшими битами. Если обнаружено достаточно большое количество подобных символов (больше 30%), то файл считается двоичным, иначе текстовым. Любой файл с пустым первым блоком рассматривается как двоичный.

Если эти операции применяются к файловым дескрипторам Perl, то проверяется содержимое буфера ввода/вывода, а не первого блока файла. Обе эти операции, примененные к файловым дескрипторам, возвращают булево значение Истина, если связанный с дескриптором файл пуст или установлен на конец файла.

При выполнении унарных именованных операций проверки файла на самом деле неявно вызывается функция stat(), причем результаты ее вычисления кэшируются, что позволяет использовать специальный файловый дескриптор _ для ускорения множественных проверок файла:

If(-s("filename") && -T _) { # Что-то делаем для текстовых файлов не нулевого размера. . . . . . . . . . . . . . }

chdir

Изменение текущего рабочего каталога на каталог, определяемый значением параметра ВЫРАЖЕНИЕ. Если параметр опущен, домашний каталог становится текущим. Возвращает бклево значение Истина в случае успешного выполнения операции замены текущего каталога и Ложь в противном случае.

Chdir [ВЫРАЖЕНИЕ]

chmod

chmod СПИСОК

Функция chmod() изменяет права доступа для файлов, представленных в списке, переданном ей в качестве параметра. Первым элементом этого списка должно быть трехзначное восьмеричное число, задающее права доступа для владельца, пользователей из группы, в которую входит владелец, и прочих пользователей. Каждая восьмеричная цифра определяет право на чтение файла, запись в файл и его выполнение (в случае если файл представляет выполняемую программу) для указанных выше групп пользователей. Установленные биты ее двоичного представления отражают соответствующие права доступа к файлу. Например, если установлены все три бита (восьмеричное число 7), то соответствующая группа пользователей обладает всеми перечисленными правами: может читать из файла, записывать в файл и выполнять его. Значение равное 6 определяет право на чтение и запись, 5 позволяет читать из файла, выполнять его, но не позволяет записывать в этот файл и т.д. Обычно не выполняемый файл создается с режимом доступа 0666 - все пользователи могут читать и записывать информацию в файл, выполняемый файл - с режимом 0777. Если владелец файла желает ограничить запись в файл пользователей не его группы, то следует выполнить следующий оператор:

Chmod 0664, "file.dat";

Возвращаемым значением функции chmod(), как и функции chown(), является количество файлов из списка, для которых операция изменения прав доступа завершилась успешно.

В операционных системах DOS и Windows имеет значение только установка режимов доступа владельца.

chown

chown СПИСОК

Любой пользователь, создавший собственный файл, считается его владельцем. Изменить владельца файла из сценария Perl можно функцией chown(). Параметром этой функции является список, первые два элемента которого должны представлять числовые идентификаторы uid и gid. Остальные элементы списка являются именами файлов, для которых изменяется владелец. Эта функция возвращает количество файлов, для которых операция изменения владельца и группы прошла успешно.

Пример:

@list = (234, 3, "file1.dat", "file2.dat"); $number = chown(@list); warn "Изменился владелец не у всех файлов!" if $number != @list-2;

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

chroot

Определяет новый корневой каталог для всех относительных (начинающихся с косой черты "/") имен файлов процесса пользователя и порожденных им процессов. Не меняет текущий рабочий каталог. В отсутствии параметра используется значение специальной переменной $_. Может вызываться только суперпользователем.

Chroot ИМЯ_КАТАЛОГА

close

close ДЕСКРИПТОР

По завершению работы с файлом он закрывается функцией close(). Единственным необязательным параметром этой функции является дескриптор, ассоциированный с файлом.

Эта функция возвращает значение Истина, если успешно очищен буфер ввода/вывода и закрыт системный дескриптор файла. Вызванная без параметра, функция close закрывает файл, связанный с текущим дескриптором, установленным функцией select().

При возникновении ошибок закрытия файла их можно обнаружить применяя специальную переменную $!: close (FILE) or die "Ошибка закрытия файла: $!";

closedir

Закрывает каталог, ассоциированный с дескриптором каталога, заданным параметром ДЕСКРИПТОР. Возвращает булево значение Истина, если каталог успешно закрыт.

Closedir ДЕСКРИПТОР

fcntl

Реализует системную команду Unix fcntl(2). Перед использованием следует получить доступ к определениям системных констант оператором use Fcntl.

Возвращаемое значение: если системная функция возвращает -1, то функция Perl - неопределенное значение; если системная функция возвращает 0, то функция Perl строку "0 but true"; если системная функция возвращает какое-либо другое значение, функция Perl возвращает это же значение.

Fcntl ДЕСКРИПТОР, ФУНКЦИЯ, СКАЛЯР

glob

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

Glob ВЫРАЖЕНИЕ

ioctl

Реализует системную команду Unix ioctl(2). Перед использованием следует получить доступ к определениям системных констант оператором require "ioctl.ph";

Возвращаемое значение:

  • если системная функция возвращает -1, то функция Perl - неопределенное значение;
  • если системная функция возвращает 0, то функция Perl строку "0 but true";
  • если системная функция возвращает какое-либо другое значение, функция Perl возвращает это же значение.
fcntl ДЕСКРИПТОР, ФУНКЦИЯ, СКАЛЯР

link

Link СТАРЫЙ, НОВЫЙ

lstat

Возвращает список значений полей структуры индекснего дескриптора символической ссылки на файл. Если параметр опущен, то используется значение специальной переменной $_.

Lstat [ДЕСКРИПТОР] lstat [ВЫРАЖЕНИЕ]

Используется для получения информации о символических ссылках. Возвращает список значений полей структуры индексного дескриптора самой ссылки, а не файла, на который она ссылается. Эта функция работает аналогично функции stat().

mkdir

Создание нового каталога с именем, заданным в параметре КАТАЛОГ, и режимом доступа, определяемым параметром РЕЖИМ. При успешном создании каталога возвращает булево значение Истина, в противном случае Ложь и в переменную $! заносится сообщение об ошибке.

Mkdir КАТАЛОГ, РЕЖИМ

open

open ДЕСКРИПТОР, ИМЯ_ФАЙЛА; open ДЕСКРИПТОР;

Для доступа к файлу из программы Perl необходим дескриптор. Для создания дескриптора используется функция open(). При выполнении операции open с заданым в параметрах именем файла открывается соответствующий файл и создается дескриптор этого файла. В качестве дескриптора файла можно использовать выражение - его значение и будет именем дескриптора. Имя файла задается непосредственно в виде строкового литерала или выражения, значением которого является строка. Операция open без имени файла открывает файл, имя которого содержится в скалярной переменной $ДЕСКРИПТОР, которая не может быть лексической переменной, определенной функцией my().

Пример:

#! perl -w $var = "out.dat"; $FILE4 = "file4.dat"; open FILE1, "in.dat"; # Имя файла задано строкой open FILE2, $var; # Имя файла задано переменной open FILE3, "/perlourbook/01/".$var; # Имя файла вычисляется в выражении open FILE4; # Имя файла в переменной $FILE4

Если задано не полное имя файла, то открывается файл с указанным именем и расположенный в том же каталоге, что и программа Perl. Можно задавать полное имя файла, однако следует иметь в виду, что оно зависит от используемой операйионной системы. Например, в Windows следует обязательно задавать имя диска: d:/perlbook/file1.doc

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

  • < (чтение)
  • > (запись)
  • >> (добавление)

Если префикс опущен, то по умолчанию файл открывается в режиме чтения.

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

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

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

Perl позволяет открыть файл еще в одном режиме - режиме чтения/записи.

Для этого перед префиксом чтения <, записи > или добавления >> следует поставить знак +.

  • +< - сохраняют содержимое открываемого файла
  • +> - сначало очищает содержимое открываемого файла
  • +>> - сохраняют содержимое открываемого файла, запись в файл всегда осуществляется в конец содержимого файла

opendir

Открытие каталога, имя которого равно значению параметра ВЫРАЖЕНИЕ, и связывает его с дескриптором, определяемым параметром ДЕСКРИПТОР. Имена дескрипторов каталогов хранаятся в собственном пространстве имен таблицы имен Perl.

Opendir ДЕСКРИПТОР, ВЫРАЖЕНИЕ

readlink

Возвращает значение сиволической ссылки, определяемой параметром ВЫРАЖЕНИЕ, если символические ссылки реализуются операционной системой; в противном случае - фатальная ошибка. Если при получении значения символической ссылки были получены системные ошибки, возвращает неопределенное значение и в специальную переменную $! заносится сообщение об ошибке. Если параметр опущен, используется значение переменной $_.

Readlink [ВЫРАЖЕНИЕ]

rename

Переименовывает файл. Возвращает 1 в случае успешного переименования и 0 в противном случае.

Rename СТАРОЕ_ИМЯ, НОВОЕ_ИМЯ

stat

В файловой структуре UNIX информация о файле храниться в его индексном дескрипторе (inode). Структура индексного дескриптора состоит из 13 полей, для которых используются специальные обозначения:

Поле Описание
dev Номер устройства в файловой системе
ino Номер индексного дескриптора
mode Режим файла (тип и права доступа)
nlink Количество жестких ссылок на файл (в отсутствии ссылок равно 1)
uid Числовой идентификатор владельца файла
gid Числовой идентификатор группы владельца файла
rdev Идентификатор устройства (только для специальных файлов)
size Размер файла в байтах
atime Время последнего обращения к файлу с начала эпохи
mtime Время последнего изменения файла с начала эпохи
ctime Время изменения индексного дескриптора с начала эпохи
blksize Предпочтительный размер блока для операций ввода/вывода
blocks Фактическое количество выделенных блоков для размещения файла

Не все перечисленные поля структуры индексного дескриптора поддерживаются всеми файловыми системами.

Функция stat() предназначена для получения значений полей структуры индексного дескриптора файла. Ее единственным параметорм может быть либо имя файла, либо дескриптор открытого в программе файла. Она возвращает список из 13 элементов, содержащих значения полей структуры индексного дескриптора файла в том порядке, как они перечислены в таблице.

Типичное использование в программе Perl представлено ниже:

($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($filename);

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

@inode = stat($filename);

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

Если при обращении к функции stat() не указан параметр, то она возвращает структуру индексного дескриптора файла, чье имя содержится в специальной переменной $_.

Функция получения информации о файле при успешном выполнении в списковом контексте возвращает список значений полей структуры индексного дескриптора файла или пустой список в случае неудачного завершения. В скалярном контексте она возвращает булево значение Истина или Ложь в зависимости от результатов своего выполнения.

Для удобства использования информации о файле функция stat() при успешном выполнении кэширует полученные значения полей. Если вызвать эту функцию со специальным дескриптором файла _ (символ подчеркивания), то она возвратит информацию, хранящуюся в кэше от предыдущего ее вызова. Это позволяет проверять различные атрибуты файла без повторного вызова функции stat() или сохранения результатов ее выполнения в переменных программы.

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

symlink

Symlink СТАРОЕ_ИМЯ, НОВОЕ_ИМЯ

umask

Устанавливает маску режима доступа процесса, заданную значением параметра ВЫРАЖЕНИЕ (восьмеричное число), и возвращает предыдущее значение маски режима доступа.

Umask ВЫРАЖЕНИЕ

unlink

Удаление файлов, определенных параметром СПИСОК. Возвращает количество успешно удаленных файлов.

Unlink СПИСОК

utime

utime СПИСОК

В структуре индексного дескриптора файла существует три поля, в которых храниться время последнего обращения (atime) к файлу, его изменения (mtime) файла и изменения индексного дескриптора (ctime). Функцией utime() можно изменить время последнего обращения и модификации файла. Ее параметром является список, содержащий имена обрабатываемых файлов, причем первые два элемента списка - числовые значения нового времени последнего доступа и модификации:

@files = ("file1.dat", "file2.dat"); $now = time; utime $now, $now, @files;

В этом фрагменте кода время последнего доступа и модификации файлов из списка @files изменяется на текущее время, полученное с помощью функции time.

Отметим, что при выполнении функции utime() изменяется и время последней модификации индексного дескриптора (ctime) - оно устанавливается равным текущему времени. Возвращаемым значением является количество файлов, для которых операция изменения времени последнего доступа и модификации прошла успешно.

Главная страница » PERL » Циклы и ветвления.

Файловый ввод и вывод.

ФАЙЛОВЫЙ ВВОД И ВЫВОД Perl специально разрабатывался для того, чтобы служить адек- ватным средством для чтения и записи в текстовые файлы. Тем не менее, как вы узнаете далее, Perl выполняет функции по произ- вольному доступу и вводу-выводу бинарных файлов. Операции по ра- боте с файлами требуют указатель файла (file handle), который яв- ляется переменной, соответствующей конкретному файлу. По умолча- нию каждый скрипт на языке Perl имеет три стандартных указателя, которые Perl автоматически открывает при запуске скрипта: STDJN, STDOUT, STDERR. Эти три стандартных указателя отвечают стандар- тным потокам STDIN, STDOUT, STDERR языка программирования С. Кро- ме того, скрипт языка Perl может открыть дополнительные указате- ли для других специфических файлов. ОТКРЫТИЕ ФАЙЛОВ И ДРУГИХ ПОТОКОВ Для того чтобы скрипт использовал файл, он должен вызвать функцию open. Она имеет следующий вид: open(FileHandle[, FileName]) В отличие от функции open библиотеки времени выполнения язы- ка С, функция open языка Perl не содержит параметра mode в вызо- ве функции. Perl определяет режим (mode) открытия файла, основы- ваясь на имени файла. Таблица 12.3 иллюстрирует связь режима от- крытия файла и имени файла. Имя файла Операция Открыть файл только для чтения (аналогично функции fopen) FILE> Создать файл для записи (как функции fopen) >FILE> Открыть файл для добавления в его конец (как функции fopen) FILE> Создать файл для чтения/записи (как функции fopen) Открыть канал из процесса, исполняющего команду Открыть канал процессу, исполняющему команду Табл. 12.3. Соглашение об именах и режимах доступа файлов языка Perl Примечание: Режим канального (pipe) потока может существовать не на всех системах. Если в вызове функции open опущено имя файла, то Perl подра- зумевает, что имя файла содержится в строковой переменной $FileHandle. Когда скрипт завершил использование файла, он закры- вает его, используя функцию close, как показано ниже: close(FileHandle); фрагмент программы иллюстрирует использование функций open и close: open(InFile, "test.dat") || die; # открываем для чтения # test.dat open(OutFile, ">test.dat") || die; # создаём test.dat $AuxFile = ">>test.dat"; open(Aux, $AuxFile) || die; # открывает для дополнения # test.dat close(InFile); close(OutFile); close(Aux); Обратите внимание, что указатели файлов не имеют обычных од- носимвольных префиксов. Как вы узнаете далее, скрипты языка Perl могут хранить имена указателей в виде строк скалярных переменных и передавать указатель любой функции, которая может их обрабаты- вать. При необходимости Perl выполняет конвертацию значений. В операционной системе MS-DOS Perl поддерживает дополни- тельную функцию, которая называется hinmode и позволяет файлово- му вводу/выводу переключаться между текстовым и бинарным режима- ми. В большинстве же систем различие между текстовым и бинарным режимами не имеет значения. Однако для операционной системы MS-DOS символ новой строки представляет собой последовательность из двух символов (CR+LF). Поскольку большинство программ не ожи- дают встретить два символа в конце строки, то система ввода/выво- да должна выполнить преобразование. Для того чтобы можно было ис- пользовать функцию binmode, соответствующий указатель может быть открыт. Функция binmode имеет следующий формат: binmode(FileHandle); ПОСТРОЧНОЕ ЧТЕНИЕ И ЗАПИСЬ ДАННЫХ Простейшим способом для чтения скриптом строки из файла слу- жит использование оператора. В языке Perl указа- тель файла, окруженный треугольными скобками, становится симво- лом ввода (input-symbol). Например, следующий фрагмент программы иллюстрирует использование символа ввода для чтения и вывода на экран содержимого файла Test.dat. open(InFile, "Test.dat") || die; while ($line =) { print $line; # Выведет строку из файла } close(InFile); Когда символ ввода достигает конца файла, он возвращает зна- чение false, которое в данном случае заканчивает выполнение цик- ла while. Существует специальный (пустой) символ ввода, обозна- чаемый, который имеет весьма специальное, но полезное примене- ние. В первый раз, когда скрипт использует пустой символ ввода, он анализирует аргументы командной строки. Если строка @ARGV является пустой, то входной символ читает из STDIN. Если вмес- то того @ARGV не пуста, то Perl открывает первый из файлов, ука- занных в переменной @ARGV, и читает содержимое файла. Когда Perl заканчивает обработку одного файла, он приступает к следующему. После того как скрипт прочитал все файлы, символ возвращает значение false. Скрипты языка Perl также могут использовать символ ввода для чтения всего содержимого файла в массив так, что каждая строка файла становится элементом массива. Например, следующая инструк- ция читает из файла STDIN в массив @lines: @lines = ; Запись данных в файл также достаточно проста. Фактически вы это делали всякий раз, когда использовали функцию print. Полный формат функции print имеет следующий вид: print List; Если функция print не получает в качестве аргумента указате- ля файла, то она посылает вывод в STDOUT. Следующий фрагмент программы иллюстрирует использование функции print для добавле- ния данных в выходной файл: open(LogFile, ">>logfile.dat") || die; ############## ($m, $d, $y) = (localtime(time)) ; print LogFile "Captain"s log, Stardate ++m$/$d/$y\n"; close(LogFile); Примечание: Указатель файла и выходной список не разделяются за- пятой. ЧТЕНИЕ И ЗАПИСЬ БЛОКОВ ДАННЫХ Программисты часто рассматривают текстовые файлы как тексто- вые потоки просто потому, что один символ следует за другим до маркера конца файла. Если скрипт должен работать с файлом, кото- рый ориентирован на работу с блоками, а не потоками, то скрипт может использовать функции sysread и syswrite для обработки фик- сированных блоков данных. Функции sysread и syswrite имеют сле- дующие форматы: $result = sysread(FileHandle, $Var, Length[, Offset]); $result = syswrite(FileHandle, $Var, Length[, Offset]); Если в вызове функций указывается сдвиг от начала файла (Offset), то функции выполнят поиск места, с которого они начнут операции ввода/вывода. Функции sysread и syswrite обе передают данные, используя скалярную переменную строкового типа. Пос- кольку функции обрабатывают фиксированные блоки памяти, то дан- ные могут содержать бинарные значения, включая нули и маркеры конца файла. Если в вызове функции указывается сдвиг от начала файла (Offset), то функция выполняет поиск места в файле, с кото- рого начинает выполнять операции ввода/вывода. Если вы работаете с блоками данных, то скрипты могут также использовать следующие функции ввода/вывода: $result = seek(FileHandle, Position, Base); $result = tell(FileHandle); $result = eof(FileHandle); Функция seek работает в точности так же, как fseek - фун- кция библиотеки времени выполнения языка С. Параметр Position за- дает позицию относительно начала отсчета, которая в свою очередь задается параметром Base следующим образом: ? 0 Поиск от начала файлов? 1 Поиск от текущей позиции? 2 Поиск от конца файла Функция tell языка Perl работает в точности так же, как фик- ция ftell библиотеки времени выполнения языка С. Эта функция воз- вращает текущую позицию в файле, с которой выполняются операции чтения или записи. Наконец, функция eof, так же как и функция feof языка С, возвращает значение или, кото- рое скрипт может использовать для определения достижения конца файла. ОБРАБОТКА БИНАРНЫХ ДАННЫХ Хотя Perl ориентирован в первую очередь на обработку текста, он также может обрабатывать бинарные данные. Скрипты могут пере- мещать бинарные данные частями, используя строковые переменные, и выполнять байтовые операции ввода/вывода, используя функции sysread и syswrite. Однако для того, чтобы выполнить что-нибудь с данными, скрипт вынужден конвертировать данные в свои скалярные форматы. ХРАНЕНИЕ БИНАРНЫХ ДАННЫХ Когда скрипт на языке Perl читает блок бинарных данных, ис- пользуя функцию sysread, он помещает эти бинарные данные в ска- лярную строковую переменную. Perl не заботится о том, что это за данные, содержат ли они нули или значения, не являющиеся ASCII-символами. В пределах символьной строки Perl принимает бай- ты как байты. В отличие от языка С, Perl не использует строк, оканчивающихся нуль-символом. Если данные соответствуют кодовой таблице ASCII, то скрипт может их обрабатывать, как любой текст. Но если данные представляют собой бинарные величины, то скрипт обязан распаковать их перед тем, как Perl сможет обработать эти данные. РАСПАКОВКА СТРОК БИНАРНЫХ ДАННЫХ В ПЕРЕМЕННЫЕ ЯЗЫКА PERL Для того чтобы скрипт получил доступ к бинарным данным, он должен распаковать их, перейдя в свой скалярный формат. Скрипты Perl распаковывают данные, используя функцию unpack, которая имеет следующий формат: $result = unpack(Template, Expression); Expression является обычной строковой переменной, которая содержит бинарные данные, прочитанные функцией sysread, но может быть также выражением, которое необходимо интерпретировать как строку. Template представляет собой символьную строку-шаблон, описывающую, как интерпретировать значения в операнде Expression. Следующий фрагмент программы иллюстрирует использование функции unpack: ($r, $g, $b) = unpack("C3", $color);# распакует в 3 символа @longwords = unpack("L*", $data); # распакует в список длинных # слов @stuff = unpack("S2L", $bin); # распакует в 2 shorts и long Каждый символ шаблона может сопровождаться числом, указываю- щим, сколько раз использовать этот символ. Если вместо числа стоит звездочка (*), то операция будет выполняться для всех ос- тающихся данных в строке. Если число не поставлено, то она выпол- няется однократно. Скрипт может поместить любое число символов шаблона в строку Template. В таблице 12.4 перечисляются символы, входящие в строковый параметр Template вместе с описанием влия- ния каждого из них на выполнение функции unpack. Символ шаблона Описание a Строка ASCII без нулевого символа А Строка ASCII без нулевого символа b Битовая строка (младший бит идет первым) В Битовая строка (старший бит идет первым) с Однобайтовый символ со знаком С Однобайтовый символ без знака d Значение с плавающей запятой, двойной точности f Значение с плавающей запятой, одинарной точности шаблона h Строка шестнадцатиричных значений (младшие разряды идут первыми) Н Строка шестнадцатиричных значений (старшие разряды идут первыми) i Целое со знаком I Целое без знака l Целое со знаком типа long L То же, только без знака n Короткое целое N Длинное целое p Указатель на строку s Короткое целое со знаком S Короткое целое без знака u Раскодировка строки v Короткое целое V Длинное целое х Пропустить вперед один байт Х Пропустить назад один байт @ Перейти на указанную позицию в строке Табл. 12.4. Символы шаблона УПАКОВКА ДАННЫХ В БИНАРНЫЕ СТРОКИ Для вывода бинарных данных скрипт должен запаковать скаляр- ные величины в строки бинарных символов. Для этого используется функция pack, формат которой указан ниже: $result = pack(Template, List); Следующий фрагмент программы иллюстрирует использование фун- кции pack: $color = pack("C3", $r, $g, $b); $data = pack("L*", @longword); $bin = pack("S2L", @stuff); Функция pack использует те же самые символы шаблона, что и функция unpack, за исключением символов а. А, и, х, X, @. РАБОТА С КАТАЛОГАМИ Perl предоставляет не только широкий набор функций для обра- ботки файлов, но также несколько очень удобных функций для скани- рования каталогов. В следующих разделах мы рассмотрим некоторые из основных функций для работы с каталогами в деталях. ОТКРЫТИЕ, ЧТЕНИЕ И ЗАКРЫТИЕ КАТАЛОГОВ Скрипты на языке Perl позволяют открывать и читать содержи- мое файлов. Точно так же эти скрипты открывают каталоги и читают имена содержащихся в них слайдов. Для открытия каталога скрипты используют функцию opendir, передавая указатель каталога и путь к нему. Для чтения списка файлов, содержащихся в каталоге, скрипт использует функцию readdir. Наконец, для закрытия каталога ис- пользуется функция closedir. Следующий фрагмент программы иллюс- трирует использование функции readdir для того, чтобы вывести на экран список файлов в текущем каталоге: opendir(Dir, $INC) || die; while ($file = readdir(Dir)) { print "$file \n" } closedir(Dir); В этом фрагменте используется переменная $INC Format, List); $result = sprintf(Format, List); По умолчанию функция printf посылает форматированный выход на стандартный выход STDIO, а функция sprintf возвращает формати- рованную строку. В обоих случаях формат строк почти аналогичен функциям языка С, исключая только отсутствие поддержки функциями языка Perl спецификатора длины (*). Следующий фрагмент программы иллюстрирует использование функций printf и sprintf. $precision = 2; $pi = 3.1415; printf("%.2f\n", $pi); # выведет 3.14 printf("%.${precision}f", $pi); # выведет 3.14 ВЫЗОВ ВНЕШНИХ ПРОГРАММ ИЗ СКРИПТА НА ЯЗЫКЕ PERL Будучи в известном смысле заменой скриптов shell, Perl обес- печивает поддержку системного взаимодействия, включая вызов внеш- них программ. В следующих разделах рассматривается несколько спо- собов вызова внешних программ из скриптов Perl. Имейте, однако, в виду, что позволяя скриптам выполнять системные команды, вы тем самым открываете бреши в системе безопасности вашего узла. При- держивайтесь общего правила не выполнять внешних команд из скрип- та на языке Perl. Тем не менее, если вы вынуждены выполнять внеш- ние команды из скрипта, то можете использовать для этих целей встроенные функции system, exec или fork. РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ На протяжении этой главы вы познакомились с примерами фун- кций для обработки строк. Многие из них основаны на концепции ре- гулярных выражений. Как вы видите из следующих разделов, скрипты языка Perl широко используют регулярные выражения для обработки текста. Если регулярные выражения внове для вас, то не беспокой- тесь. Спустя короткое время после того, как вы познакомитесь с несколькими разделами этой главы, регулярные выражения станут для вас просты и понятны. ОБЗОР РЕГУЛЯРНЫХ ВЫРАЖЕНИЙ Регулярные выражения являются причудливым термином, возник- шим в компьютерной науке и служащим для обозначения образца, сос- тоящего из символов. Скрипты на языке Perl используют символьные образцы просто для того, чтобы провести анализ входных данных, расщепляя их на части. Часто скрипт может проанализировать вход- ные данные, основываясь на пробелах, запятых, символах табуляции и других разделителях. Но когда входные данные имеют произ- вольный формат то лучше всего с такой задачей справляются регу- лярные выражения. СИНТАКСИС РЕГУЛЯРНЫХ ВЫРАЖЕНИЙ Для сокращения размеров регулярных выражений, Perl ис- пользует специальные символы. Таблица 12.6 содержит список неко- торых из символов, используемых скриптами языка Perl в регуляр- ных выражениях. Символ Описание. Соответствует любому символу (за исключением символа новой строки) (..) Группирует последовательность элементов + Удовлетворяет предыдущему образцу один или большее количество раз? Удовлетворяет образцу нуль или один раз * Соответствует образцу один или нуль раз [...] Соответствует символу из заданного множества [^...] Соответствует символу из множества, полученного отрицанием (...|...|...) Соответствует одной из альтернатив ^ Соответствует началу строки $ Соответствует образцу в конце строки {n, m} Соответствует образцу от n до m раз {n} Соответствует образцу точно n раз {n,} Соответствует образцу минимум n раз \n\t etc. Соответствует знаку новой линии, символу табуляции и т. д. \b Соответствует на границе слова \В Соответствует внутри границ слова \d Соответствует цифре \D Соответствует не цифре \s Соответствует пробелу \S Соответствует не пробелу \w Соответствует букве или цифре \W Соответствует символу, не являющемуся ни буквой, ни цифрой Табл. 12.6. Символы, используемые в регумрных выражениях Perl помещает регулярные выражения (образцы, шаблоны) в слэ- ши, т. е. в наклонные черточки, например, в виде /pattern/. Сле- дующий фрагмент программы иллюстрирует регулярные выражения язы- ка Perl: # the following regular expressions are true if: /ig/ # string contains "ig" /(b|d|f)ig/ # string contains "big", "dig" or "fig" /+/ # string contains a number /*/ # string contains an identifier Если эти выражения кажутся вам бессмысленными, не беспокой- тесь. В этой главе мы собираемся рассмотреть несколько регуляр- ных выражений. Сейчас просто запомните, что Perl помещает регу- лярные выражения между двумя наклонными чертами-слэшами, как по- казано выше. ИСПОЛЬЗОВАНИЕ РЕГУЛЯРНЫХ ВЫРАЖЕНИЙ ДЛЯ ПОИСКА ПО КЛЮЧЕВЫМ СЛОВАМ Скрипты языка Perl используют регулярные выражения для того, чтобы упростить сравнение строк. Для того чтобы проверить, содер- жит ли строка заданный образец, скрипт может использовать регу- лярные выражения следующим образом: if ($str =~ /pattern/) В данном случае регулярные выражения принимают значение, если образец найден в строке ($str). Если строка по со- держит образца, то выражение возвращает значение. Напри- мер, следующее выражение проверяет, содержит ли строка текст Web Programming: if ($str =~ /Web Programming/) Для того, чтобы проверить полное совпадение, выражение дол- жно привязать сравнение к началу и концу строки. Например, сле- дующее выражение имеет значением величину, если и только если переменная $str принимает одно из трех значений: ,) : ($str =~ /^ba(na) {2,4}$/) Аналогичным образом, следующее выражение истинно тогда и только тогда, когда переменная $str содержит слово и не яв- ляется частью другого слова, такого как. ($str =~ /\bthe\b/) ИСПОЛЬЗОВАНИЕ РЕГУЛЯРНЫХ ВЫРАЖЕНИЙ ДЛЯ АНАЛИЗА ВХОДНЫХ ДАННЫХ По мере усложнения ваших скриптов Perl возникнет много слу- чаев, когда вы захотите узнать больше, чем просто проверить, сов- падает ли образец со строкой или нет. Например, может потребо- ваться, чтобы скрипт извлек определенное значение строки. Используя символы группировки () внутри регулярного выражения, скрипт может извлечь соответствующие образцу значения из строки и сформировать из них список. Например, следующий фрагмент програм- мы использует регулярные выражения для того, чтобы извлечь меся- цы, дни и годы из списка: $str = " January 1, 1997, "; ($m, $d, $y) = $str =~ /\s*(\S*)\s + (\d+)\D + (\d{4})/; В этом случае можно прочитать регулярные выражения следую- щим образом: ? Пропустить вначале любой специальный символ; ? записать все символы, не являющиеся специальными, в переменную $m (переменная для обозначения месяцев); ? пропустить специальный символ; ? поместить все цифры в переменную $d (переменная для записи дней); ? пропустить все знаки, не являющиеся цифрами; ? записать четыре цифры в переменную $у (переменная для обозначения лет). Perl поддерживает также другую форму сравнения с образцом, использующую оператор (=~), который добавляет отрицание результа- та: (!~). Этот оператор эквивалентен выражению!($str =~/pattern/). РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ ДЛЯ ПОИСКА И ЗАМЕНЫ СТРОК До сих пор вы использовали операторы, проверяющие на соот- ветствие образцу. Оказывается, Perl поддерживает два других регу- лярных выражения, которые модифицируют проверяемую строковую пе- ременную. В записанной дальше инструкции Perl замещает часть строки, которая соответствует образцу, на заданную строку: $str =~ s/pattern/replacement/; Например, следующая инструкция заменит слово на: $str =~ s/\bcolour\b/color/; Небольшая модификация позволяет заменить все слова на: $str =~ s/\bcolour\b/color/g; В данном случае g в конце выражения указывает языку Perl на необходимость глобальной подстановки. Используя суффикс i, можно задать выполнение поиска с учё- том регистра. В противоположность простой проверке на соответ- ствие образцу, следующее выражение осуществляет также и замену: $str =~ tr/SearchList/ReplacementList/; Например, замена всех символов нижнего регистра теми же сим- волами верхнею регистра может быть осуществлена таким образом: $str =~ tr/a-z/A-Z/; # меняет регистр, с нижнего на верхний Проанализируйте сами следующий пример: $letters = "abcde"; print "$letters\n" # Выведет abcde $letters =~ tr/a-z/A-Z/; print "$letters\n" # Выведет ABCDE РЕЗЮМЕ В этой главе рассмотрено введение в программирование на язы- ке Perl. Используя рассмотренные здесь концепции, можно писать сложные скрипты CGI на языке Perl. Следующая глава окажет вам по- мощь в получении навыков в создании CGI-скриптов на языке Perl, которые можно запустить на собственном сервере. Прежде чем следо- вать далее, удостоверьтесь, что вы понимаете следующие ключевые концепции: ? Perl представляет собой интерпретируемый язык программирования, который используется программистами для написания скриптов для Web и Internet. ? Конструкции языка Perl во многих отношениях напоминают анало- гичные конструкции языка С, однако Perl предлагает много дополни- тельных возможностей, в особенности для обработки строк и файлов, которые трудно отыскать в языке С. ? Perl является основным языком для написания CGI-программ для Web и Internet, в первую очередь благодаря своей гибкости, ком- пактному стилю и обеспечению высокой безопасности. ВАЖНЕЙШИЕ WEB-УЗЛЫ С ИНФОРМАЦИЕЙ О PERL Следующие узлы Web помогут отыскать информацию об интересую- щих вас деталях относительно языка Pcrl, скриптов на нем, а так- же специальной информации о ресурсах языка Perl 5 и его библиоте- ках. Используйте эти Web-узлы в качестве отправной точки вашего поиска. http://www.shareware.com/top/Source-Code-table.html - SHAREWARE.COM - самые популярные файлы с кодами программ. http://www.inxpress.net:80/~moewes/computer/perl95.html - Perl для Windows 95. http://www.mit.edu:8001/perl/perlapi.html - PERLAPI http://www.genome.wi.mit.edu:80/ftp/pub/software/WWW/cgi_docs.html - CGI.pm - Библиотека Perl5.CGI http://www.metronet.com/0/perlinfo/perl5/manual/perl.html - PERL http://www.teleport.com/~rootbeer/perl.html - Ссылки для изучающих Perl

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

Чтение или запись данных из файла требует использования дескрипторов файлов.

Ручка файла (дескриптор файла) является наименовании соединений ввода / вывода.

Perl предоставляет три файла ручками: STDIN, STDOUT, STDERR, представляющие стандартный ввод, стандартный вывод и стандартный вывод ошибок.

Perl файлы могут быть открыты в следующих способов:

Open FILEHANDLE, EXPR open FILEHANDLE sysopen FILEHANDLE, FILENAME, MODE, PERMS sysopen FILEHANDLE, FILENAME, MODE

Параметр Описание:

  • EXPR: имя файла и тип доступа к файлу, состоящий из выражения.
  • РЕЖИМ: тип файла доступа.
  • Завивке: доступ Bit (биты прав доступа).

Открытая функция

Мы используем следующую функцию кода, чтобы открыть режим только для чтения (<), чтобы открыть файл file.txt:

Open(DATA, "

<Только для чтения представление.

Код файла DATA Ручка используется для чтения файла, следующий пример будет открыть файл и содержимое файла на выходе:

#!/usr/bin/perl open(DATA, "){ print "$_"; }

Следующий код для записи (>) способ открыть файл file.txt:

Open(DATA, ">file.txt") or die "file.txt 文件无法打开, $!";

> Для режима записи.

Если вам нужно открыть файл в режиме чтения-записи, перед> или <символ знак +, чтобы добавить:

Open(DATA, "+

Такой подход не удаляет содержимое исходного файла, если вы хотите удалить следующий формат:

Open DATA, "+>file.txt" or die "file.txt 文件无法打开, $!";

Если вы хотите подать дополнительные данные, дополнительные данные перед тем, вам нужно всего лишь открыть файл в режиме добавления:

Open(DATA,">>

>> Представляет добавлять данные в существующий файл, если вам нужно прочитать содержимое файла, чтобы добавить, чтобы добавить знак +:

Open(DATA,"+>>file.txt") || die "file.txt 文件无法打开, $!";

В следующей таблице перечислены различные режимы доступа:

режим описание
<Или г
> Или ж
>> Или Открыть для записи указатель файла в конец файла. Если файл не существует, делается попытка создать.
+ <Или г +
+> Или ш + Открыть для чтения и записи, указатель файла в заголовок файла и размер файла обрезается до нуля. Если файл не существует, делается попытка создать.
>> + Или + Открыть для чтения и записи указатель файла в конец файла. Если файл не существует, делается попытка создать.

функция SysOpen

ФункцияSysOpen аналогична открыть функцию, но они не являются такими же формой аргумента.

Следующий пример основан на чтение и запись (+ <имя файла) способ, чтобы открыть файл:

Sysopen(DATA, "file.txt", O_RDWR);

Если вам необходимо обновить файлы, удаленные до того, как файл записывается следующим образом:

Sysopen(DATA, "file.txt", O_RDWR|O_TRUNC);

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

Параметры завивке восьмеричное значение свойства указывает на то, что права доступа к файлам после создания, по умолчанию0x666.

В следующей таблице перечислены возможные значения режима:

режим описание
O_RDWR Открыть для чтения и записи, указатель файла в заголовке файла.
O_RDONLY Открыть только для чтения указатель файла в заголовке файла.
O_WRONLY Открыть для записи указатель файла в заголовке файла и размер файла обрезается до нуля. Если файл не существует, делается попытка создать.
O_CREAT Создайте файл
O_APPEND Append File
O_TRUNC Размер файла режется до нуля
O_EXCL Если вы используете O_CREAT файл существует, он возвращает сообщение об ошибке, он может проверить, существует ли файл
O_NONBLOCK Неблокирующая операций ввода / вывода, так что мы либо успеха или немедленно возвращает ошибку, не блокирован.

Закрыть функция

После использования в файле, закройте файл, который вы хотите обновить входные и выходные буферы дескриптор файла, связанные с закрытием файла имеет следующий синтаксис:

Close FILEHANDLE close

FILEHANDLE для указанного дескриптора файла, если успешно закрыта возвращается верно.

Close(DATA) || die "无法关闭文件";

Чтение и запись файлов

Чтение и запись информации в файл Есть несколько различных способов:

оператор

Основной метод чтения информации из открытого дескриптора файла является оператор. В скалярном контексте он возвращает одну строку из дескриптора файла. Например:

#!/usr/bin/perl print "本教程网址?\n"; $name = ; print "网址:$name\n";

После реализации описанной выше процедуры следующая информация, мы вводим вывод URL оператор печати:

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

Реализация создает import.txt файл, следующим образом:

$ cat import.txt 1 2 3

#!/usr/bin/perl open(DATA,"; print @lines; # 输出数组内容 close(DATA);

функция ЕОКП

xgetc функция возвращает один символ из указанного FILEHANDLE, если вы не указываете обратный STDIN:

Getc FILEHANDLE getc

В случае возникновения ошибки, или дескриптор файла в конце файла, то она возвращает ФДООН.

функция чтения

Функция чтения используется для обработки информации, считанной из буфера файла.

Эта функция используется для чтения двоичных данных из файла.

Read FILEHANDLE, SCALAR, LENGTH, OFFSET read FILEHANDLE, SCALAR, LENGTH

Параметр Описание:

  • FILEHANDLE: дескрипторов файлов, используемых для хранения уникального идентификатора для файла.
  • СКАЛЯР: Начать чтение позиции.
  • Длина: длина содержимого чтения.
  • OFFSET: смещение.

В случае успешного возвращения, чтобы прочитать количество прочитанных байтов, возвращает 0, если конец файла, если произошла ошибка возврата UNDEF.

функция печати

Для вся информация считывается из функций дескриптор файла на заднем конце основной функции заключается в написании печати:

Print FILEHANDLE LIST print LIST print

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

Print "Hello World!\n";

копирование файлов

В следующем примере мы открываем существующий файл file1.txt, и читать его каждую строку записывается в файл file2.txt в:

#!/usr/bin/perl # 只读方式打开文件 open(DATA1, "file2.txt"); # 拷贝数据 while() { print DATA2 $_; } close(DATA1); close(DATA2);

Переименовать файл

Ниже приведены примеры, мы уже существующий файл file1.txt переименовать file2.txt, каталог, указанный в / USR / w3big / тест / в:

#!/usr/bin/perl rename ("/usr/w3big/test/file1.txt", "/usr/w3big/test/file2.txt");

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

Удалить файлы

Следующие примеры показывают, как мы используем функциюUNLINK , чтобы удалить этот файл:

#!/usr/bin/perl unlink ("/usr/w3big/test/file1.txt");

Укажите расположение файла

Вы можете использовать функциюСКАЖИТЕ, чтобы получить местоположение файла, а также указать местоположение в файле с помощью функции искать:

скажите функцию

Функция скажите используется для получения местоположения файла:

Tell FILEHANDLE tell

Если FILEHANDLE функция возвращает позицию указателя файла в байтах. Если вы не укажете возврат к умолчанию выбирается ручкой файла.

искать функцию

искать () функция используется для перемещения через файл дескриптор файла читать и писать указатели путь для чтения или записи файла в байтах чтения и записи:

Seek FILEHANDLE, POSITION, WHENCE

Параметр Описание:

  • FILEHANDLE: дескрипторов файлов, используемых для хранения уникального идентификатора для файла.
  • ПОЛОЖЕНИЕ: указывает количество байтов дескриптора файла (чтение-запись указателя позиции), чтобы переместить.
  • ОТКУДА: представляет собой дескриптор файла (для чтения и записи указателей местоположения) начинают, когда начальное положение, вы можете принимать значение 0, 1; обозначают начало файла, текущей позиции и конец файла.

Seek DATA, 256, 0;

информация о файле

Perl файловые операции также может проверить, существует ли файл и читать и писать.

Что я могу создать file1.txt файл, например, в следующем:

$ cat file1.txt www..txt"; my (@description, $size); if (-e $file) { push @description, "是一个二进制文件" if (-B _); push @description, "是一个socket(套接字)" if (-S _); push @description, "是一个文本文件" if (-T _); push @description, "是一个特殊块文件" if (-b _); push @description, "是一个特殊字符文件" if (-c _); push @description, "是一个目录" if (-d _); push @description, "文件存在" if (-x _); push @description, (($size = -s _)) ? "$size 字节" : "空"; print "$file 信息:", join(", ",@description),"\n"; }

Вышеприведенная программа, выход:

File1.txt 信息:是一个文本文件, 15 字节

Файл операторы тестирования в следующей таблице:

операторы описание
Файл первого обращения времени (единицы: дней)
-B Является ли это двоичный файл
Файл (индексных дескрипторов) инод время модификации (единицы измерения: дней)
Файл последнего изменения времени (единицы измерения: дней)
Все файлы являются реальными UID
-R Файл или каталог может быть прочитан реальным UID / GID
-S Сокет (Socket)
-T Является ли это текстовый файл
-W Файл или каталог может быть записан в режиме реального UID / GID
-X Файлы или каталоги могут быть выполнены в режиме реального UID / GID
-b Файл блок-специальное (специальный блок) (например, монтирования диска)
Символ-специальное (специальные символы) файл (например, устройства ввода / вывода)
-d каталог
Имя файла или каталога существует
-f Обычный файл
-g Файл или каталог имеет атрибут setgid
-k Файл или каталог имеет липкий бит
-l Это является символической ссылкой
Все файлы доступны UID
-p Файл является именованным каналом (FIFO)
-r Файлы могут быть эффективно UID / GID чтения
-s Файл или каталог существует и не 0 (возвращает число байт)
-t Ручка Файл TTY (функция isatty система () возвращает результат, имя файла не может использовать этот тест)
-u Файл или каталог имеет атрибут Setuid
-w Файлы могут быть записаны в действительный UID / GID
-x Файлы могут быть выполнены эффективно UID / GID
-z Файл существует, размер 0 (константа каталога ложно), то есть, пуст ли файл,

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

В этой статье обсудим:

  • Манипуляции с файлом
  • Работа со строками в файле

    Что такое файловые манипуляторы, и с чем их едят

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

    Есть и стандартные Перловские файловые манипуляторы. Они называются STDIN (стандартный ввод), STDOUT (стандартный вывод) и STDERR (стандартный поток ошибок). Например параметры скрипту из формы передаются именно через STDIN (при условии использования метода POST).

    Если понадобится создать копию файлового манипулятора (не файла, а только манипулятора по которому осуществляется доступ к файлу), то можно воспользоваться функцией open (о ней подробнее поговорим позже).

    Пример: open(FILL,"file.txt"); open(FAIL,"<&FILL");

    О присваивании переменным файловых манипуляторов:

    $handle=*FILL; или передать его в функцию: some_sub(*FILL);

    И под конец скажу, что файловые манипуляторы в Perl используются не только для связи с, собственно, файлом. Они могут быть связаны с каким-нибудь процессом, сокетом и т.д. Но это не входит в тематику статьи.

    Манипуляции с файлом

    Открытие файла осуществляется функцией open.

    Open(FFF,"> file.txt");

    Разберемся. У функции три параметра: FFF - название файлового манипулятора (его задаете вы), режим доступа ">" и "file.txt" - имя нужного вам файла. Есть три основных режима: ">" - запись,"<"- чтение, ">>"- добавление в файл.

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

    В sysopen три обязательных параметра и один необязательный.

    Например: sysopen(FH,$name, $flags, $param);

    FH - собственно, файловый манипулятор, $name - имя файла в чистом виде (без ">" и др.). В $flags помещаем число, полученное объединением нижеописанных констант через OR (|):

    Это, конечно, не полный перечень, но здесь перечислены самые необходимые и часто используемые константы.

    И наконец $param. Этот параметр задает маску доступа к файлу и записывается в восьмеричной системе. Обычно используется значение 0666 (значение по умолчанию, то есть если $param опущен), или 0777. Первое значение используется для обычных файлов, второе же для каталогов и исполняемых файлов.

    Пример открытия файла для записи (если не найден - создается):

    Sysopen(FH,"data.txt",O_WRONLY|O_TRUNC|O_CREATE);

    Запись в файл делаем функцией print.

    Print(FFF "oppa! Пишем в файл!");

    Здесь FFF - имя файлового манипулятора, а строка в кавычках - текст, который мы хотим записать в файл, ассоциированный с FFF.

    Если до попытки открытия файла не существовало, то функция open его создаст, а если файл был, и он был не пустой, то после вышеуказанной функции print, в нем ничего не останется от предыдущей информации, а записана будет та ерунда, которую я там вписал.

    Как уже было сказано, существуют три стандартных файловых манипулятора, и при опущенном файловом манипуляторе функция print осуществит вывод в STDOUT (то же относится к функциям printf и write). Чтобы изменить направление вывода в Perl предусмотрена функция select (правда не только для этого). Пример:

    Open(F1,"> one.txt"); print "Файл открыт! Пишем в STDOUT."; $old_point=select(F1); print "Пишем в файл one.txt"; select($old_point); print "Снова пишем в STDOUT."; close(F1);

    Закрываем файл функцией close.

    Close(FFF);

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

    Блокировка файла

    Во-первых для чего? А для того, что если несколько процессов хотят одновременно заполучить доступ к файлу, причем на запись, причем еще и хотят туда что-то писать (кошмар), то представьте, что оказалось бы, если не этот чудный механизм блокировки. Он позволяет, грубо говоря, ставить процессы в очередь. Делаем так:

    Open(FIL,"> file.dat"); flock(FIL,2); close(FIL);

    О функциях open и close уже говорили, а на flock остановимся немного подробнее. Она получает два параметра - файловый манипулятор и, образно говоря, категорию блокировки.

  • 1 совместная блокировка (для чтения)
  • 2 монопольная блокировка (для записи)
  • 4 асинхронный запрос блокировки
  • 8 снятие блокировки

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

    Работа со строками в файле

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

    Для чтения строк из файла используется файловый манипулятор "поставленный" в <>.

    Например:

    Open(FIL,"data.txt"); while() { # делаем что-то с каждой строкой файла }

    Если не указано иначе, то внутри такого цикла используется стандартная переменная "$_", а номер строки записывается в "$.". Так как конец строки обозначается спецсимволом, например "\n", для получения самой строки (без эдакого "хвоста") нужно ее усечь функцией chomp.

    Open(FIL,"data.txt"); while() { chomp; # отрезается спецсимвол от переменной $_ print; # пишем $_ на STDOUT }

    @strings=; foreach $line (@strings) { print $list; }

    Для передвижения по файлу используются функции tell и seek.

    Open(FIL,"data.txt"); $position=tell(FIL); print "Текущая позиция в файле $position. \n"; seek(FIL,$position+10,1); print "А теперь переместились на 10 байт к концу файла от текущей позиции. \n"; $position=tell(FIL); print "Теперь текущая позиция в файле $position. \n";

    Результат:

    Текущая позиция в файле 0. А теперь переместились на 10 байт к концу файла. Теперь текущая позиция в файле 10.

    Функция tell принимает в качестве параметра файловый манипулятор, а seek берет три параметра. Первый - файловый манипулятор, второй - смещение в байтах, третий - направление смещение. Есть три направления смещения: 0 - от начала файла, 1 - от текущей позиции, 2 - с конца файла.

    Нельзя сказать, что это все, что нам предлагает Perl для работы с файлами. Будем надеяться, что у меня будет время на то, чтобы написать о том, как работать с каталогами, тонкости при работе с бинарными файлами, объектно-ориентированный подход к управлению файлами и их содержимым.

  • В Perl реализовано два набора функций для осуществления операций чтения/записи в файл. Функции одного набора используют буфер - некоторую область памяти - для накопления читаемой/записываемой в файл информации, после заполнения которого или закрытия файла осуществляется физическая запись данных буфера на диск или их пересылка в программу. Эти функции, к которым относятся print , readline, <>, read , getc , seek и tell , по существу, представляют собой интерфейсные функции к процедурам буферизованной библиотеки ввода-вывода stdio языка С. Использование буферизованных операций ввода-вывода ускоряет чтение/запись данных в файлы. Функции второго набора, к которым относятся sysread, syswrite и sysseek, обращаются непосредственно к функциям ввода-вывода операционной системы, осуществляя прямые физические операции чтения/записи данных без накопления их в промежуточном буфере. Открывать файл для доступа как буферизованными, так и небуферизованными функциями можно любой из двух функций - open () или sysopen() - при открытии файла не регламентируется, каким набором функций следует обрабатывать содержащуюся в нем информацию. Единственное требование заключается в том, что не рекомендуется смешивать эти два подхода для одного файла в одном сеансе открытия, так как это может привести к непредсказуемым результатам.

    ВНИМАНИЕ При работе с одним и тем же файлом не следует смешивать вызовы буферизованных и небуферизованных функций ввода-вывода. Подобная практика может приводить к непредсказуемым коллизиям. Если требуется, например, использовать небуферизованных функции чтения/записи, а информация из файла уже читалась буферизованной операцией о, то следует закрыть файл, снова его открыть и использовать для работы с ним небуферизованные функции.

    Буферизованный ввод-вывод

    Чаще всего в программе осуществляется обработка текстовых файлов. Операция <>, операндом которой является дескриптор файла, читает информацию из файла целыми «записями», которые обычно представляют строки текстового файла. Примененная в скалярном контексте, она читает текущую запись файла, увеличивая на единицу специальную переменную $., отслеживающую количество прочитанных записей. В списковом контексте эта же операция прочитает все записи файла, если она выполняется для этого файла первой, или оставшиеся записи, если до нее были выполнены другие операции чтения из файла, и возвращает список, элементами которого являются прочитанные записи файла. Более точно можно сказать, что операция <> в списковом контексте читает оставшиеся записи файла, начиная с текущей его позиции, которая неявно изменяется при каждой операции чтения, а может быть изменена и явным способом с помощью функции seek (), c которой мы познакомимся чуть позже. Забегая вперед, скажем, что все файлы в Perl не имеют никакой структуры, а представляются, как и в С, потоком байтов. Разделитель записей хранится в специальной переменной $/, и по умолчанию им является символ новой строки \n. Таким образом, если пользователь не устанавливал собственный разделитель записей, то под записью файла в операции <> подразумевается строка текстового файла. Задание другого разделителя записей осуществляется обычной операцией присваивания переменной $/ нового символа или последовательности символов разделителя записей. В листинге 6.9 демонстрируются некоторые приемы чтения из файла операцией <>. Листинг 6.9. Чтение из файла операцией <> #! perl -w open (F1, "in.dat") or die "Ошибка открытия файла: $!"; open(F2, "out.dat") or die "Ошибка открытия файла: $!"; $line1 = ; # Первая запись файла in.dat $line2 = ; # Вторая запись файла in.dat @rest = ; # Оставшиеся записи файла in.flat $/ = ">"; # Задание другого разделителя записей @f2 = ; # Печать прочитанных записей файла out.dat for($i=0; $i<=$#f2; $i++) { print "Запись ".($i+1).": $f2[$i]\n"; } $/ = "\n"; # Восстановление разделителя по умолчании close (Fl) or die $!; close(F2) or die $!; open(F3, "out.dat") or die "Ошибка открытия файла: $!"; print ; # Печать всего файла close(F3) or die $!; Несколько комментариев к программе из листинга 6.9. В переменные $line1 и $line2 читаются соответственно первая и вторая строки файла in.dat, так как используется умалчиваемый разделитель записей \n. Элементы массива @rest хранят строки с третьей по последнюю этого же файла, так как в операторе присваивания операция чтения выполняется в списковом контексте. Перед чтением записей файла out.dat устанавливается новый разделитель записей - символ >. Если файл out.dat, например, содержит только одну строку Иванов> Петров> Сидоров> Конец то элементы массива @f2 будут содержать следующие значения: $f2 = "Иванов>" $f2[l] = "Петров>" $f2 = "Сидоров>" $f2 = "Конец"
    ПРИМЕЧАНИЕ Если при создании файла out.dat его единственная строка завершена переходом на новую строку (нажата клавиша Enter), то $f2 будет содержать строку "Конец\n".
    В последнем операторе печати программы из листинга 6.9 операция выполняется в списковом контексте, так как функция print() является списковой операцией и ей требуется список значений. Если же мы захотели бы при выводе на печать предварить каждую запись каким-либо текстом и предполагали бы для этого использовать следующий оператор: print "Запись:".; то получили бы распечатку только первой строки файла, так как в этом случае операция будет выполняться в скалярном контексте, создаваемом операцией конкатенации строк (.). Чтобы получить требуемый результат, следовало бы воспользоваться циклом while: while() { print "Запись: ".$_; # Печать очередной строки связанного # с дескриптором F3 файла } Напомним, что если результат операции <> не присваивается никакой переменной, то результат ее выполнения сохраняется в специальной переменной S_. Фактически операция чтения записей <> в Perl реализуется встроенной функцией readline(), которую можно вызывать и непосредственно. Единственным ее параметром является ссылка на дескриптор файла, а так как дескриптор не принадлежит ни к одному из допустимых типов данных (скаляр, массив скаляров или хэш-массив), то следует использовать ссылку на специальный внутренний тип данных Perl typeglob. Для этого достаточно поставить перед дескриптором файла префикс *: readline *ДЕСКРИПТОР; Например, следующие два оператора полностью эквивалентны: $line = ; $line = readline *STDIN; Естественно, все, что говорилось о символах разделения записей, хранящихся в специальной переменной $/, относится и к операции readline(). Запись в файл, открытый в режиме записи или добавления, осуществляется функцией print() с первым параметром, являющимся дескриптором файла: print ДЕСКРИПТОР СПИСОК_ВЫВОДА; Эта операция записывает содержимое элементов списка в том порядке, в котором они определены в вызове функции, и не добавляет в конец списка никакого разделителя записей или символа перехода на новую строку. Об этом должен позаботиться сам программист, либо явно добавляя в конец списка вывода символ разделителя записей или новой строки, либо воспользовавшись возможностью, предоставляемой специальной переменной $\. Функция print добавляет в конец своего списка вывода содержимое этой специальной переменной, которая по умолчанию содержит пустую строку: # Явное задание разделителя записей print F1 @recl1, "\n"; $\ = "\n"; # Установка разделителя записей # Теперь разделитель записей будет выводиться неявно # каждой следующей функцией print print F1 @rесl2;
    ВНИМАНИЕ Между дескриптором файла и первым элементом списка вывода не должно быть запятой. Если такое случится, то интерпретатор perl выдаст ошибку: No comma allowed after filehandle.
    При записи информации в файл функцией print() можно воспользоваться еще одной полезной возможностью. Если задано значение специальной переменной $, то оно вставляется между элементами списка вывода. Например, если мы хотим, чтобы значения элементов списка выводились не сплошным потоком символов, а были разделены пробелом, то следует установить значение этой специальной переменной равным пробелу: $var1 = "11111"; Svar2 = "22222"; print $var1, $var2, "\n"; $, = " "; print $var1, $var2, "\n"; Первый оператор print напечатает: 1111122222 Тогда как при выполнении второго оператора print мы получим строку: 11111 22222
    ВНИМАНИЕ При установке значений специальных переменных $\ и $, их действие распространяется на все последующие вызовы функции print().
    Если в функции print не указан дескриптор файла, то по умолчанию вывод осуществляется в стандартный файл вывода с дескриптором STDOUT, а если не задан список вывода, то выводится содержимое специальной переменной $_. Установку дескриптора функции print() по умолчанию можно изменить стандартной функцией select (). Вызванная без параметров, она возвращает текущий дескриптор файла вывода по умолчанию для функций print() и write(). Если ей передается единственный параметр, то этот параметр должен быть дескриптором файла. В этом случае она также возвращает текущий дескриптор по умолчанию и меняет его на дескриптор, определенный переданным ей параметром. Пример использования функции select() приведен ниже. # Сохранение текущего дескриптора по умолчанию и назначение # F1 новым умалчиваемым дескриптором $oldfilehandle = select (Fl); # Вывод в файл, ассоциированный с дескриптором Fl print $line; # Восстановление старого дескриптора по умолчанию select($oldfilehandle); # Вывод в файл, ассоциированный со старым дескриптором print $line; Как уже отмечалось, файлы в Perl интерпретируются как неструктурированные потоки байтов. То, что с помощью операции <> и функции print() мы соответственно читаем или записываем целую последовательность байтов, которую мы называем «записью», ни в коем случае не связано с какой-то определенной структурой файла. Просто эти операции так организованы, что одна читает, а вторая записывает последовательности байтов. В действительности мы можем читать и записывать информацию в файл побайтно. Для каждого открытого файла создается системная переменная, которая отслеживает его текущую позицию, то есть место в файле, начиная с которого функции чтения читают, а функции записи записывают информацию. Следовательно, мы можем говорить, что операции чтения/записи выполняются с текущей позиции файла. При выполнении любой операции чтения/записи указатель текущей позиции файла перемещается на количество прочитанных или записанных байтов. Если, например, была прочитана запись длиной 80 байт с самого начала файла, то следующая операция чтения или записи начнется с позиции 81 байта файла. Для определения текущей позиции в файле используется функция tell(), единственным параметром которой может быть дескриптор файла. Она возвращает текущую позицию в ассоциированном с заданным дескриптором файле. Эта же функция без параметра возвращает текущую позицию в файле, для которого была в программе выполнена последняя операция чтения. Текущая позиция в файле автоматически изменяется в соответствии с выполненными операциями чтения/записи, но ее можно менять и явным образом с помощью функции seek(), которой передаются в качестве параметров дескриптор файла, смещение и точка отсчета. Для связанного с дескриптором файла устанавливается новая текущая позиция, смещенная на заданное параметром СМЕЩЕНИЕ число байтов относительно точки отсчета: seek ДЕСКРИПТОР, СМЕЩЕНИЕ, ТОЧКА__ОТСЧЁТА; Параметр ТОЧКА_ОТСЧЕТА может принимать одно из трех значений: 0 - начало файла, 1 - текущая позиция, 2 - конец файла. Смещение может быть как положительным, так и отрицательным. Оно отрицательно относительно конца файла, положительно относительно начала файла и может быть как положительным, так и отрицательным относительно текущей позиции. Задать точки отсчета можно так же с помощью именованных констант SEEK_SET, SEEK_CUR и SEEK_END, определенных в поставляемом с Perl пакете IO::Seekable, что делает программу лучше читаемой. Эти константы в том порядке, как мы их перечислили, соответствуют началу файла, текущей позиции и концу файла. Для использования указанных именованных констант, естественно, необходимо подключить в программе этот модуль с помощью ключевого слова use . Например, следующие операторы устанавливают одинаковые текущие позиции в файлах: use IO::Seekable: seek FILE1, 5, 0; seek FILE2, 5, SEEK_SET; В языке нет специальных функций перехода в начало или конец файла. Если необходимо позиционировать файл в начало или конец, следует использовать нулевое смещение относительно соответствующих точек отсчета при вызове функции seek(): seek FILE1, 0, 0; # Переход в начало файла seek FILE1, 0, 2; # Переход в конец файла Кроме уже знакомых нам операций чтения записей файла <> и readline(), Perl предоставляет еще две функции чтения содержимого файлов - getc() и read(). Первая читает один байт из файла, тогда как вторая читает записи заданной длины, то есть последовательность байтов определенной длины. Функция getc() читает и возвращает символ в текущей позиции файла, дескриптор которого передан ей в качестве параметра, или неопределенное значение в случае достижения конца файла либо возникновения ошибки. Если функция вызывается без параметра, то она читает символ из стандартного файла ввода STDIN. getc; # Чтение символа из STDIN getc F1; # Чтение символа в текущей позиции файла с # дескриптором F1 Функция read() читает определенное число байтов, начиная с его текущей позиции. Она может вызываться с тремя или четырьмя параметрами, и ее вызов имеет вид: read ДЕСКРИПТОР, ПЕРЕМЕННАЯ, ДЛИНА [,СМЕЩЕНИЕ]; Эта функция читает количество байтов, определенное целым значением параметра ДЛИНА, в скалярную переменную, определяемую параметром ПЕРЕМЕННАЯ, из файла с дескриптором, заданным первым параметром ДЕСКРИПТОР. Возвращаемое значение - действительное количество прочитанных байтов, 0 при попытке чтения в позиции конца файла и неопределенное значение в случае возникновения других ошибок. Необязательный параметр СМЕЩЕНИЕ определяет, после какого байта содержимого переменной ПЕРЕМЕННАЯ будет сохранена прочитанная из файла запись. Он может иметь и отрицательное значение смещения -n (n - целое число). Это означает, что из содержимого переменной ПЕРЕМЕННАЯ отбрасываются последние n байтов и к оставшейся строке добавляется запись, прочитанная из файла. Листинг 6.10 демонстрирует чтение записей определенной длины из файла in.dat, содержащего три строки данных: ******** * PERL * ******** Листинг 6.10. Чтение записей определенной длины #! perl -w open(F1, "in.dat") or die "Ошибка открытия файла: $!"; $str = "1234567890"; read F1, $str, 9; # Чтение девяти байтов в # переменную $str без смещения print $str,"\n"; # $str = "********\n" read F1, $str, 8, length ($str); print $str,"\n"; # $str - "*******\n* PERL *" В программе из листинга 6.10 функция length() используется для определения количества символов (байтов), содержащихся в скалярной переменной. После выполнения первой операции чтения содержимое переменной $str было уничтожено, так как эта функция read () вызывалась без смешения. При втором чтении хранившиеся данные в переменной $str были полностью сохранены. Обратите внимание, что символ перехода на новую строку, содержащийся в первой строке файла in.dat, также учитывается при чтении функцией read() записей определенной длины. Следует не забывать об этом обстоятельстве при чтении информации из «многострочного» файла функцией read().

    Небуферизованный ввод-вывод

    Функции чтения из файла sysread(), записи в файл syswrite() и установки указателя текущей позиции файла sysseek() являются аналогами рассмотренных нами функций read(),print() и seek(), но, в отличие от последних, они напрямую обращаются к соответствующим функциям операций системы, а не к функциям стандартной библиотеки ввода-вывода С, минуя тем самым создаваемый этими функциями буфер для выполнения операций чтения и записи в файл. Заметим, что аналога буферизованной функции tell () не существует, ее функциональность реализуется функцией sysseek(). При вызове функций небуферизованного чтения и записи им передается одинаковый набор параметров, полностью соответствующий параметрам функции read: sysread ДЕСКРИПТОР, ПЕРЕМЕННАЯ, ДЛИНА [,СМЕЩЕНИЕ]; syswrite ДЕСКРИПТОР, ПЕРЕМЕННАЯ, ДЛИНА [,СМЕЩЕНИЕ]; Возвращаемым значением этих функций является истинное количество соответственно прочитанных или записанных в файл байтов, 0 в случае достижения конца файла или undef при возникновении ошибки. Соответственно набор параметров функции sysseek() полностью соответствует передаваемым параметрам в функцию seek(): sysseek ДЕСКРИПТОР, СМЕЩЕНИЕ, ТОЧКА_ОТСЧЕТА; Все сказанное относительно использования функции seek() полностью переносится и на ее небуферизованный аналог. Функциональность буферизованной операции tell() реализуется следующим вызовом функции sysseek(): $position = sysseek Fl, 0, 1; # Текущая позиция указателя файла Программа демонстрирует использование небуферизованных функций ввода-вывода для обработки содержимого файла. #! perl -w use Fcntl; # Открытие файла в режиме чтение/запись sysopen F1, "in.dat", O_RDWR; # Чтение блока в 14 байтов $read = sysread F1, $string, 14; warn "Прочитано $read байтов вместо 14\n" if $read != 14; # Установка текущей позиции (на 15 байтов) $position = sysseek Fl, 0, 1; die "Ошибка позиционирования: $!\n" unless defined $position; # Запись строки в текущей позиции $string = "Новое Значение"; $written = syswrite F1, $string, length ($string); die "Ошибка записи: $!\n" if $written != length($string); # Закрытие файла close F1 or die $!; При работе с небуферизованными функциями ввода-вывода следует всегда проверять завершение операции чтения, записи или позиционирования. Стандартная система ввода-вывода, через которую реализуется буферизованный ввод-вывод, сама проверяет завершение указанных операций и отвечает за него, если процесс по каким-то причинам был прерван на середине записи. При небуферизованном вводе-выводе об этом должен позаботиться программист.