Таблица 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. Если требуется направить информацию в другой поток, то перед списком выводимых данных указывается файловый дескриптор. Обратите внимание, что между файловым дескриптором и списком выводимых значений запятая не ставится. Вот примеры вывода данных: