Пятница, 24.11.2017, 10:20
Приветствую Вас Гость | RSS
Главная | Лекции | Регистрация | Вход
Меню сайта
Форма входа
Логин:
Пароль:
Категории раздела
Лекция [24]
Мини-чат
100
Поиск
Наш опрос
Оцените мой сайт
Всего ответов: 2
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0
    Программирование Perl
    Главная » Статьи » Лекция » Лекция

    Лекция 9.1: Средства ввода-вывода

    Потоки ввода-вывода

    Система ввода-вывода Perl основана на принципах, заложенных в системе Unix и распространившихся на все современные операционные системы. Одним из основных понятий работы в программе с внешними данными являются потоки ввода-вывода. В программе обращение к потоку ввода-вывода производится через файловый манипулятор (file handle), иногда неправильно называемый дескриптором файла. При запуске любой программы автоматически открывается три потока: стандартный ввод (stdin), стандартный вывод (stdout) и стандартный протокол (stderr). Поток стандартного ввода в диалоговой операционной средесвязывается с клавиатурной, а потоки стандартного вывода и стандартного протокола - с дисплейной частью консолиоперационной системы. Со стандартными потоками в Perl связываются три предопределенных файловых манипулятора: соответственно STDINSTDOUT и STDERRСвязывание имени файла с пользовательским файловым манипулятором в программе выполняется с помощью операции open(), открывающей поток обмена данными с указанным файлом. Требования надежности рекомендуют обязательно проверять все операции ввода-вывода на успешное завершение. Поэтому в случае возникновения ошибки при открытии файла программа обычно аварийно завершается с помощью функции die(), которая может выводить диагностическое сообщение в стандартный поток протокола. Например, так открывается файл и создается файловыйманипулятор FILE_HANDLE:

     
    # открыть для чтения файл по имени, взятом из $file_name
    open(FILE_HANDLE, $file_name)
    # или аварийно завершить программу с выдачей сообщения
     or die("Ошибка открытия файла $file_name: $!\n"); #
     

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

     
    open my $file_handle, $file_name
     or die "Ошибка открытия файла $file_name: $!\n";
     

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

     

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

     
    Таблица 9.1. Основные режимы открытия потоков ввода-вывода
    Обозначение Режим открытия Пример использования
    < Чтение (существующего файла с начала) open($fh, '</temp/buffer.txt')
    > Перезапись (с начала файла) open($fh, '>/temp/buffer.txt')
    >> Дозапись (в конец файла) open($fh, '>>/temp/buffer.txt')
    +< Чтение и запись (файл должен существовать) open($fh, '+</temp/buffer.txt')
    +> Запись и чтение (файл усекается) open($fh, '+>/temp/buffer.txt')
    +>> Дозапись и чтение open($fh, '+>>/temp/buffer.txt')
     

    Применяются две формы записи функции open(): старая с двумя аргументами, когда режим открытия указывается перед именем файла, и новая - с тремя аргументами, в которой режим открытия указывается отдельно вторым параметром. Сравните:

     
    open $fh, '</temp/buffer.txt';
    open $fh, '<', '/temp/buffer.txt';
     

    Программисты, знающие язык C, могут воспользоваться для открытия потоков функцией sysopen(), которая аналогична функции открытия потоков в C, и к тому же позволяет более тонко настраивать режимы открытия файлов. А вообще в комплекте с Perl идет целый учебник по функции open(), который можно прочитать утилитой чтения документации:

     
    perldoc perlopentut
     

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

     
    close(FILE) or die("Ошибка при закрытии файла: $!\n");
    close $handle or die "Ошибка закрытия файла: $!\n";
     

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

     
    open my $in, "<:encoding(UTF-8)", 'utf8.txt' or die;
    open my $out, ">:encoding(cp1251)", 'cp1251 .txt' or die;
    while(<$in>){ print $out $_; }
    close $in or die; 
    close $out or die;
     

    В некоторых операционных системах (например, в MS-DOS), после открытия файла, но перед чтением двоичных данных требуется установить для файлового манипулятора режим работы с двоичными данными с помощью функции binmode($file_handle). При работе в операционных системах, не требующих установки этого режима, вызов функции binmode() не оказывает никакого действия.

    Построчный ввод-вывод

    В огромном числе случаев ввод данных в Perl-программу и вывод из нее результатов производится построчно, а для разделения строк файла используется разделитель входных записей, хранящийся в специальной переменной $/ ($INPUT_RECORD_SEPARATOR). Для чтения одной строки из входного потока используется операция "кристалл" (diamond), которой в качестве аргумента передается файловый манипулятор или переменная, содержащая манипулятор. Если аргумент не указан, данные читаются из стандартного входного потока.

     
    $input = <>; # чтение строки в $input из STDIN
    $line = <FILE>; # чтение строки в $line из потока FILE
    $in = <$handle>; # чтение строки в $in из потока $handle
     

    Операция чтения "кристалл" в скалярном контексте возвращает одну строку вместе с разделителем записей, а когда достигаетсяконец файла, она возвращает неопределенное значение undef, которое воспринимается как ложное. Поэтому типичный цикл построчного чтения данных проверяет прочитанное значение и заканчивается, когда оно становится неопределенным:

     
    open my $fh, "< $file" or die "Ошибка открытия: $!";
    while (my $line = <$fh>) { # чтение строки в переменную $line
     chomp $line; # удаление разделителя строк
     print length $line, " $line\n"; # обработка строки
    }
    close $fh or die "Ошибка закрытия: $!";
     

    Операция чтения "кристалл" в списочном контексте возвращает список всех строк с разделителями записей. Так, например, можно считать файл в массив, попутно отсортировав его:

     
    @lines= sort(<$fh>); # в @lines отсортированные строки из $fh
     

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

     
    print($list, $of, $output, $values); # вывод в STDOUT
    print STDOUT $list, $of, $output, $values; # вывод в STDOUT
    print(STDERR $list, $of, $output, $values); # вывод в STDERR
    print FILE $list, $of, $output, $values; # вывод в FILE
    print($file $list, $of, $output, $values); # вывод в $file
     

    Для форматирования выводимой информации применяется функция printf(), которая преобразует выходные данные при помощи форматов преобразования, подробно объясненных в "лекции 7" при описании функции sprintf(). Например, так можно вывести отформатированное текущее время в разные выходные потоки:

     
    my ($hh, $mm, $ss) = (localtime)[2, 1, 0]; 
    # выбрать из списка нужные значения: часы, минуты, секунды
    my $format = "%02d:%02d:%02d\n"; # формат вывода
    
    printf $format, $hh, $mm, $ss; # вывод в STDOUT
    printf(STDERR $format, $hh, $mm, $ss); # вывод в STDERR
    printf $file $format, $hh, $mm, $ss; # вывод в $file
     

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

     

    Встроенный файл данных

    В файле с исходным текстом программы на Perl может располагаться встроенный файл с данными, которые помещаются в конце программного файла после специальной лексемы __END__ (в основной программе) или __DATA__ (в программном модуле). При выполнении программы данные из этого встроенного файла доступны для чтения при помощи специального файловогоманипулятора DATA. Во встроенном файле удобно хранить тестовые данные для проверки работы программы после ее модификации. Вот пример чтения данных из встроенного файла:

     
    while (my $line = <DATA>) { # читаем построчно данные
     print $line; # обрабатываем данные
    }
    __END__
    Это данные из встроенного файла
    Категория: Лекция | Добавил: mazay (13.05.2014)
    Просмотров: 92 | Рейтинг: 0.0/0
    Всего комментариев: 0
    Добавлять комментарии могут только зарегистрированные пользователи.
    [ Регистрация | Вход ]
    Создать бесплатный сайт с uCozCopyright MyCorp © 2017