perlopentut
СОДЕРЖАНИЕ
- ИМЯ
- ОПИСАНИЕ
- Открытие текстовых файлов
- Открытие бинарных файлов
- Открытие каналов
- Открытие файлов на низком уровне с помощью sysopen
- СМОТРИТЕ ТАКЖЕ
- АВТОР И АВТОРСКИЕ ПРАВА
ИМЯ
perlopentut - простые рецепты для открытия файлов и каналов в Perl
ОПИСАНИЕ
Всякий раз, когда вы выполняете ввод-вывод с файлом в Perl, вы делаете это через то, что в Perl называется дескриптором файла. Дескриптор файла — это внутреннее имя внешнего файла. Функция open отвечает за установление связи между внутренним именем и внешним именем, а функция close отвечает за разрыв этой связи.
Для вашего удобства Perl настраивает несколько специальных дескрипторов файлов, которые уже открыты при запуске. К ним относятся STDIN, STDOUT, STDERR, и ARGV. Поскольку они предварительно открыты, вы можете использовать их сразу, не тратя времени на их открытие самостоятельно:
print STDERR "This is a debugging message.\n";
print STDOUT "Please enter something: ";
$response = <STDIN> // die "how come no input?";
print STDOUT "Thank you!\n";
while (<ARGV>) { ... } Как видно из этих примеров, STDOUT и STDERR — это выходные дескрипторы, а STDIN и ARGV — входные дескрипторы. Они написаны заглавными буквами, потому что они зарезервированы для Perl, так же как массив @ARGV и хеш %ENV.
Связи с внешними объектами были установлены вашей оболочкой.
Вам необходимо самостоятельно открывать все остальные дескрипторы файлов. Хотя существует много вариантов, наиболее распространённый способ вызова функции open() Perl — с тремя аргументами и одним возвращаемым значением:
OK = open(HANDLE, MODE, PATHNAME)
Где:
- OK
-
будет какое-то определённое значение, если открытие выполнено успешно, но
undefв случае ошибки; - HANDLE
-
должно быть неопределённой скалярной переменной, которая будет заполнена функцией
openпри успешном открытии; - MODE
-
— режим доступа и формат кодировки для открытия файла;
- PATHNAME
-
— внешнее имя файла, который нужно открыть.
Большая часть сложности функции open заключается в большом количестве возможных значений параметра MODE.
Ещё один момент перед тем, как мы покажем, как открывать файлы: открытие файлов не (обычно) автоматически блокирует их в Perl. См. perlfaq5 для информации о блокировке.
Открытие текстовых файлов
Открытие текстовых файлов для чтения
Если вы хотите прочитать текстовый файл, сначала откройте его в режиме только для чтения так:
my $filename = "/some/path/to/a/textfile/goes/here";
my $encoding = ":encoding(UTF-8)";
my $handle = undef; # this will be filled in on success
open($handle, "< $encoding", $filename)
|| die "$0: can't open $filename for reading: $!"; Как и в оболочке, в Perl используется "<" для открытия файла в режиме только для чтения. При успешном открытии Perl выделяет новый дескриптор файла и заполняет ваш ранее неопределённый аргумент $handle ссылкой на этот дескриптор.
Теперь вы можете использовать такие функции, как readline, read, getc, и sysread с этим дескриптором. Наиболее распространённой функцией ввода является функция, которая выглядит как оператор:
$line = readline($handle);
$line = <$handle>; # same thing Поскольку функция readline возвращает undef в конце файла или при ошибке, вы иногда увидите её использование таким образом:
$line = <$handle>;
if (defined $line) {
# do something with $line
}
else {
# $line is not valid, so skip it
} Также можно быстро die на неопределённое значение таким образом:
$line = <$handle> // die "no input found"; Однако, если достижение конца файла — ожидаемое и нормальное событие, вы не хотите выходить просто из-за того, что исчерпаны данные. Вместо этого вы, вероятно, просто хотите выйти из цикла ввода. Затем вы можете проверить, произошла ли ошибка, которая привела к завершению цикла, и действовать соответственно:
while (<$handle>) {
# do something with data in $_
}
if ($!) {
die "unexpected error while reading from $filename: $!";
} Замечание о кодировках: необходимость каждый раз указывать кодировку может показаться немного обременительной. Чтобы установить стандартную кодировку для open, чтобы не указывать её каждый раз, можно использовать псевдоним open:
use open qw< :encoding(UTF-8) >; После этого вы можете безопасно опустить часть кодировки в режиме открытия:
open($handle, "<", $filename)
|| die "$0: can't open $filename for reading: $!"; Но никогда не используйте простой "<" без предварительной установки стандартной кодировки. В противном случае Perl не сможет определить, какой из многих возможных форматов текстового файла у вас есть, и Perl не будет знать, как правильно преобразовать данные вашего файла в реальные символы, с которыми он может работать. Другие распространенные форматы кодировок включают "ASCII", "ISO-8859-1", "ISO-8859-15", "Windows-1252", "MacRoman", и даже "UTF-16LE". См. perlunitut для получения дополнительной информации о кодировках.
Открытие текстовых файлов для записи
Когда вы хотите записать в файл, сначала вам нужно решить, что делать с любым существующим содержимым этого файла. У вас есть два основных варианта: сохранить или перезаписать.
Если вы хотите сохранить существующее содержимое, вам нужно открыть файл в режиме добавления. Как и в оболочке, в Perl вы используете ">>" для открытия существующего файла в режиме добавления. ">>" создаёт файл, если он ещё не существует.
my $handle = undef;
my $filename = "/some/path/to/a/textfile/goes/here";
my $encoding = ":encoding(UTF-8)";
open($handle, ">> $encoding", $filename)
|| die "$0: can't open $filename for appending: $!"; Теперь вы можете записывать в этот дескриптор файла, используя любую из функций print, printf, say, write, или syswrite.
Как отмечалось выше, если файла ещё нет, режим добавления создаст его для вас. Но если файл уже существует, его содержимое защищено от повреждения, потому что вы добавляете свой новый текст после конца старого текста.
С другой стороны, иногда вам нужно перезаписать всё, что там может быть. Чтобы очистить файл перед записью в него, вы можете открыть его в режиме записи:
my $handle = undef;
my $filename = "/some/path/to/a/textfile/goes/here";
my $encoding = ":encoding(UTF-8)";
open($handle, "> $encoding", $filename)
|| die "$0: can't open $filename in write-open mode: $!"; Здесь снова Perl работает так же, как оболочка, в том смысле, что ">" перезаписывает существующий файл.
Как и в режиме добавления, при открытии файла в режиме записи вы теперь можете записывать в этот дескриптор файла, используя любую из функций print, printf, say, write, или syswrite.
А как насчёт режима чтения-записи? Вероятно, вам следует предположить, что его не существует, потому что открытие текстовых файлов в режиме чтения-записи вряд ли даст нужный результат. Подробности см. в perlfaq5.
Открытие бинарных файлов
Если файл, который нужно открыть, содержит бинарные данные, а не символы текста, то аргумент MODE функции open немного отличается. Вместо указания кодировки вы сообщаете Perl, что ваши данные представлены в виде сырых байтов.
my $filename = "/some/path/to/a/binary/file/goes/here";
my $encoding = ":raw :bytes"
my $handle = undef; # this will be filled in on success И затем откройте, как раньше, выбрав "<", ">>", или ">" по мере необходимости:
open($handle, "< $encoding", $filename)
|| die "$0: can't open $filename for reading: $!";
open($handle, ">> $encoding", $filename)
|| die "$0: can't open $filename for appending: $!";
open($handle, "> $encoding", $filename)
|| die "$0: can't open $filename in write-open mode: $!"; В качестве альтернативы, вы можете изменить режим на бинарный для существующего дескриптора файла следующим образом:
binmode($handle) || die "cannot binmode handle"; Это особенно полезно для дескрипторов файлов, которые Perl уже открыл для вас.
binmode(STDIN) || die "cannot binmode STDIN";
binmode(STDOUT) || die "cannot binmode STDOUT"; Вы также можете передать binmode явную кодировку, чтобы изменить её на лету. Это не совсем режим "бинарный", но мы всё ещё используем binmode для этого:
binmode(STDIN, ":encoding(MacRoman)") || die "cannot binmode STDIN";
binmode(STDOUT, ":encoding(UTF-8)") || die "cannot binmode STDOUT"; После того, как ваш бинарный файл правильно открыт в нужном режиме, вы можете использовать все те же функции ввода-вывода Perl, что и для текстовых файлов. Однако вы можете использовать функцию read с фиксированным размером вместо readline с переменным размером для ввода.
Вот пример того, как скопировать бинарный файл:
my $BUFSIZ = 64 * (2 ** 10);
my $name_in = "/some/input/file";
my $name_out = "/some/output/flie";
my($in_fh, $out_fh, $buffer);
open($in_fh, "<", $name_in)
|| die "$0: cannot open $name_in for reading: $!";
open($out_fh, ">", $name_out)
|| die "$0: cannot open $name_out for writing: $!";
for my $fh ($in_fh, $out_fh) {
binmode($fh) || die "binmode failed";
}
while (read($in_fh, $buffer, $BUFSIZ)) {
unless (print $out_fh $buffer) {
die "couldn't write to $name_out: $!";
}
}
close($in_fh) || die "couldn't close $name_in: $!";
close($out_fh) || die "couldn't close $name_out: $!"; Открытие каналов
Будет объявлено.
Открытие файлов на низком уровне с помощью sysopen
Будет объявлено. Или удалено.
СМОТРИТЕ ТАКЖЕ
Будет объявлено.
АВТОР И АВТОРСКИЕ ПРАВА
Авторское право 2013 Тома Кристиансена.
Эта документация бесплатна; вы можете распространять и/или изменять её на тех же условиях, что и Perl сам по себе.
© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.28.3/perlopentut