1. Главная страница » Компьютеры » Perl работа с файлами

Perl работа с файлами

Автор: | 16.12.2019

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    O_RDONLY Только для чтения
    O_WRONLY Только для записи
    O_RDWR Для чтения и для записи
    O_CREAT Если файла нет, создать!
    O_APPEND Открытие в режиме присоединения
    O_TRUNC Очищаем содержимое при открытии

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

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

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

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

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

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

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

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

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

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

    Читайте также:  Hd 6870 vs gtx 560

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

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

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

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

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

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

    Можно прочитать строки в массив:

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

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

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

    Буду очень благодарен за сообщения о возможных ошибках и неточностях в этой статье.

    Работа с данными

    Создание файла, открытие файла, запись в файл

    Файл можно открыть для чтения, записи в конец файла, перезаписи, чтения/записи. Для этого нужно использовать префиксы:

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

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

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

    Чтение данных из файла

    Чтение из файла осуществляется построчно.

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

    Как переименовать файл

    Функция rename — переименовывает указанный список файлов. Возвращает 1 в случае успешного переименования, в другом случае — 0.

    Как получить информацию о файле (дата создания и т.п.)

    Функция stat возвращает информацию в списковом контексте, в следующем порядке:

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

    Начало эпохи датируется 1 января 1900 года 0 часов 0 минут.

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

    Как изменить время последнего обращения к файлу и его модификации

    Функция позволяет utime() изменить время последнего обращения (atime) и модификации файла (mtime) .

    Основы Perl — ввод/вывод, файлы, каталоги и глобы

    С момента публикации моего предыдущего урока программирования на Perl прошло уже более двух месяцев. И вот она — долгожданная последняя часть!

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

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

    Читайте также:  Gps навигатор с радар детектором

    Ввод и вывод

    Как всегда, давайте начнем с примера:

    #!/usr/bin/perl
    use strict ;

    while ( my $line = ) <
    chomp ( $line ) ; # отсекаем символ

    last if ( $line eq "exit" ) ;
    print "Вы ввели ‘$line’. Для выхода из цикла введите exit
    " ;
    >

    Рассмотрим четвертую строку. STDIN — это файловый дескриптор, связанный со стандартным потоком ввода. Чтение из файла производится с помощью оператора «треугольные скобки». Да, это не так привычно, как readln, но такая запись тоже имеет право на жизнь, тем более, что она короче.

    Функция chomp проверяет, находится ли в конце строки-аргумента символ новой строки (
    ) и если он присутствует, отсекает его. Если такого символа нет, строка остается без изменений.

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

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

    Приведенный выше скрипт можно немного «ужать» за счет использования переменной $_. Напоминаю, что впервые мы столкнулись с ней во втором уроке.

    #!/usr/bin/perl
    use strict ;

    while ( ) < # результат чтения сохраняется в переменной $_
    chomp ; # отсекаем символ
    в переменной $_
    last if ( $_ eq "exit" ) ;
    printf "Вы ввели ‘%s’. Для выхода из цикла введите exit
    " , $_ ;
    >

    Заметьте также, что функция print была заменена на printf , которая должна быть хорошо знакома программистам на Си. Я полагаю, что вы уже знакомы с форматированным выводом. Если это не так — ничего страшного, всю необходимую информацию можно получить, выполнив команды perldoc -f printf и perldoc -f sprintf .

    Файлы — чтение и запись

    Чтение и запись в случае с файлами производится точно так же, как чтение из STDIN и запись в STDOUT или STDERR. Единственное, о чем следует позаботится — это создать дескриптор, связанный с заданным файлом.

    Собственно создание файлового дескриптора происходит на четвертой строчке. Функция open принимает два аргумента — дескриптор и имя файла. В случае ошибки, например, если файла с именем input.txt не существует, функция вернет false, а сообщение об ошибке будет записано в переменную $! .

    Но что делает оператор «или» после вызова open? Конструкция вида «функция1 or функция2» встречается в perl-скриптах довольно часто, так что давайте разберемся, как она работает.

    Будем считать, что функция1 и функция2 возвращают ложь в случае ошибки и истину иначе. Сначала выполняется функция1. Если она завершается успешно, будет возвращено истинное значение и интерпретатору Perl следует вычислить «истина или (что-то, что вернет функция2)». Но «истина или ложь» = «истина или истина» = «истина». Другими словами, в этом случае результат не зависит от того, что вернет функция2, а значит не следует тратить время на ее выполнение.

    Если же функция1 завершится с ошибкой и вернет «ложь», то результат «ложь или функция2» напрямую зависит от того, что вернет функция2, значит в этом случае интерпретатор будет обязан ее вызвать. Таким образом конструкция «функция1 or функция2» означает «вызвать функцию1 и если она вернет ложь (и только в этом случае!) вызвать функцию2».

    Значит, если вызов open завершится неудачно, будет вызвана функция die , которая делает что? Как несложно догадаться по ее названию — выводит сообщение об ошибке и завершает работу скрипта. Остальная часть примера настолько тривиальна, что я не вижу смысла ее описывать.

    Только что мы рассмотрели открытие файла на чтение. Чтобы открыть файл на запись, нужно перед его именем указать > или >>:

    #!/usr/bin/perl
    use strict ;
    # пример 1
    open F >, ">output1.txt" ; # один знак "больше"
    or die "Failed to open output1.txt: $!
    " ;
    print F >"111
    " ; # обратите внимание — запятой нет
    close F >;

    # пример 2
    open F >, ">>output2.txt" ; # два знака "больше"
    or die "Failed to open output2.txt: $!
    " ;
    print F >"222
    " ;
    close F >;

    В первом случае, если файл output1.txt уже существует, он будет очищен, иначе — файл output1.txt будет создан. Во втором случае, если файл output2.txt уже существует, запись будет производится в его конец, иначе также будет создан новый файл. Чтобы почувствовать разницу, можете несколько раз запустить этот скрипт и посмотреть, что будет записано в каждом из файлов.

    Читайте также:  Acer aspire timeline ultra m3 581tg

    Здесь мы рассмотрели лишь самые распространенные способы вызова функции open . Вывод команды perdoc -f open занимает 19 килобайт. Это не случайно, ведь функцию open можно вызывать с тремя аргументами, с ее помощью можно сохранять файловые дескрипторы в скалярных переменных и даже перенаправлять данные в уже открытых дескрипторах. Разумеется, в рамках одной заметки я не могу рассказать о всех возможностях этой функции (более того — скорее всего я их всех и не знаю), так что можете считать чтение соответствующей документации домашним заданием.

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

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

    Работа с каталогами

    Самый простой способ получить имена всего, что есть в каталоге — это воспользоваться функциями opendir и readdir :

    Тут все настолько просто, что даже комментировать не хочется. Давайте лучше сразу перейдем к более интересному примеру:

    #!/usr/bin/perl
    use strict ;

    /*.txt" ;
    print "$_
    " for ( @flist ) ;

    Функция glob возвращает список файлов, как это сделала бы оболочка csh. Тильда означает домашний каталог, звездочка — любую последовательность символов. Также можно использовать знак вопроса, фигурные и квадратные скобки.

    Существует и более короткая запись:

    А еще можно так:

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

    Другие операции над файлами и каталогами

    Эта заметка была бы не полной, если бы я не рассказал, как в Perl создать/удалить каталог или определить размер файла. Но не беспокойтесь, этот раздел очень простой. Фактически сейчас моя задача — привести список функций и операторов, чтобы в случае необходимости вы знали, в какой мануал заглянуть (вы ведь уже запомнили команду «perldoc -f имя_функции», верно?) :

    # удаление одного или нескольких файлов
    # функция возвращает число успешно удаленных файлов
    unlink $file1 , $file2 , $file3 ;

    # а еще можно так:
    unlink glob "

    # переименовать или переместить файл
    rename $old , $new ;

    # создать каталог, второй аргумент представляет
    # собой права доступа и является необязательным
    mkdir $dir_name , 0755 ;

    # удалить пустой каталог
    rmdir dir ;

    # сменить права доступа к файлу или файлам
    chmod 0755 , $file1 , $file2 , $file3 ;

    # сменить владельцев файлов
    chown $user , $group , glob "*.txt"

    # по моему опыту работать с ссылками приходится не часто
    # но на всякий случай вот список имен функций:
    # link, symlink, readlink

    Также в Perl имеется несколько довольно полезных операторов:

    С непривычки эти операторы могут показаться странными, но на самом деле они мало чем отличаются от банальных «больше» и «меньше». Полный список операторов этого типа можно посмотреть, выполнив команду perldoc -f -X .

    Заключение

    Мои поздравления! Вы только что закончили читать последнюю часть «Основ Perl». Теперь вы знаете, что в этом языке нет ничего мистического — он не то, чтобы невероятно сложен, очень даже читаем, если знаешь матчасть, и хорошо документирован. К сожалению, за кадром остались еще множество вопросов, например взаимодействие процессов, объектно-ориентированное программирование, регулярные выражения и многие другие. Если вы намерены продолжить изучение Perl, то я настоятельно рекомендую приобрести книги «Изучаем Perl» и «Perl: изучаем глубже», авторы — Шварц Р. и Феникс Т., пока их еще легко найти.

    Я надеюсь, что «основы» помогут вам написать ваши первые скрипты и разобраться в чужом коде. Со временем у вас будут возникать вопросы «а как мне сделать то-то» и «а что происходит в этом скрипте в строе N». Не ленитесь заглядывать в документацию и просить помощи у более опытных программистов на форумах, в чатах и в тематических сообществах (например, жж-сообществе ru_perl). И рано или поздно вы станете настоящим гуру языка Perl. Удачи!

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

    Добавить комментарий

    Ваш e-mail не будет опубликован. Обязательные поля помечены *

    *

    code