Габор Сабо. Файлы в Perl 6
Габор Сабо подготовил серию видеоуроков, посвященных основам Perl 6. Вашему вниманию предлагается русский перевод четвертой части — про файлы. Оригинальный скринкаст на английском языке доступен на ютубе.
Привет! Меня зовут Габор Сабо. Это четвертая часть обучающих материалов о Perl 6. На этот раз я расскажу про файлы. Остальные презентации можно найти по ссылкам на странице szabgab.com/perl6.html.
Рассказывать о языке, о его структурах данных или об управляющих конструкциях не особо полезно, если нет возможности читать файлы и записывать в них. Так что давайте посмотрим, как это делается в Perl 6.
use v6; my $content = slurp "text.txt"; say $content.chars;
В первую очередь надо обратить внимание на оператор slurp, которым мы уже пользовались. Он получает имя файла и считывает все его содержимое в переменную, помещая ее в скаляр $content.
Slurp читает все, включая переводы строк и все строки. Поэтому если распечатать переменную $content, напечатается все, что было в файле. Для презентации это слишком много, поэтому я вызову метод .chars, который напечатает число символов в этом файле.
Вновь переходим к интерактивному режиму, как и в предыдущие разы, и вызываем slurp, eval и имя файла:
slurp eval '01.p6'423
Печатается число символов в файле.
Если же прочитать то же самое в массив, программисты Perl 5 могут подумать, что это считает файл построчно. Но в Perl 6 это не так.
use v6; my @content = slurp "text.txt"; say @content.elems; say @content[0].chars;
В Perl 6 slurp всегда читает весь файл в виде единственной строки, так что у массива будет только один элемент. Если вызвать метод .elems, увидим в результате один элемент в массиве, который содержит весь файл.
Так что если запустить второй пример, мы увидим, что здесь только один элемент, и он того же размера, что и в предыдущем случае.
slurp eval '02.p6'1 423
Чтобы в Perl 6 прочитать каждую строку отдельно, нужно использовать функцию lines.
use v6; my @content = lines "text.txt"; say @content.elems; say @content[0].chars;
Она так же получает имя файла, но возвращает содержимое построчно.
Выполнив программу, увидим, что в файле 12 строк, и в первой строке 39 символов.
slurp eval '03.p6'12 39
Очевидно, и slurp, и lines бесполезны, если файл очень большой. В этих случаях мы хотим просматривать файлы строка за строкой, что-то с ними делать, и идти дальше. В этом случае в памяти будет только одна строка.
Вот как это делать:
use v6;
for lines "text.txt" -> $line {
say $line.chars;
}
Здесь мы пользуемся циклом for, а внутри — опять функцией lines. В этом случае lines выполняется отложенно, то есть она будет читать строки одна за другой, и на каждой итерации помещать содержимое строки в скалярную переменную $line, а затем выполняется блок.
Сейчас в блоке мы вызываем на этой переменной метод .chars, печатая число символов в этой строке.
eval slurp '04.p6'39 0 67 78 0 76 56 0 86 9 0 0
Видим, что в первой строке 39 символов, затем идет пустая строка, затем — 67 и так далее.
Кроме того, можно открыть файл и выполнить чтение из него.
use v6;
my $fh = open "text.txt";
my $first_line = $fh.get;
say $first_line;
for $fh.lines -> $line {
say $line.chars;
}
Для этого используем функцию open. Она принимает имя файла и возвращает файловый дескриптор. С файлом можно делать разные действия, например, прочитать одну строку, используя метод .get:
my $first_line = $fh.get;
Он вернет одну строку, и мы можем ее распечатать.
Или можно вызвать на файловом дескрипторе метод .lines, который будет читать строки одна за другой:
for $fh.lines -> $line {
say $line.chars;
}
Очевидно, поскольку мы уже считали одну строку, здесь будут читаться все строки, начиная со второй.
Выполняем и видим первую строку из файла, вторая строка была пустая, и так далее:
eval slurp '05.p6'Introduction to Perl 6 - part 4 - files 0 67 78 0 76 56 0 86 9 0 0
Последнее, что я хочу сегодня показать, — как записывать в файл.
use v6;
my $fh = open "out.txt", :w;
$fh.say("text 3");
$fh.close;
say slurp "out.txt";
В этом случае мы также вызываем функцию open, передаем ей имя файла, в который собираемся записывать, а затем — параметр :w, сообщающий, что файл открывается для записи.
По умолчанию, если не указывать дополнительный параметр, файл открывается для чтения.
Возвращается файловый дескриптор, и затем на нем мы можем вызвать метод .say со строкой, и она напечатается в файл.
Например, если я заменю текст на "text 4" и выполню программу, появится новое содержимое:
eval slurp '06.p6'text 4
Почему? Потому что после печати я вызвал метод .close. В Perl это не обязательно, но в некоторых случаях это важно, чтобы убедиться, что все записано в файл. Иначе Perl буферизирует вывод, а как только я закрыл файл, я смогу вызвать slurp, и он напечатает то, что мы видели.
Еще раз напомню, что остальные части вы можете найти по ссылке szabgab.com/perl6.html. Спасибо.