Perl 6

Габор Сабо. Файлы в 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. Спасибо.

cast, open, slurp, lines, get, files — 1 августа 2010