perlopentut
СОДЕРЖАНИЕ
- НАЗВАНИЕ
- ОПИСАНИЕ
- Открытие текстовых файлов
- Открытие двоичных файлов
- Открытие каналов
- Открытие файлов на низком уровне с помощью sysopen
- СМОТРИТЕ ТАКЖЕ
- АВТОР и АВТОРСКИЕ ПРАВА
НАЗВАНИЕ
perlopentut - простые рецепты для открытия файлов и каналов в Perl
ОПИСАНИЕ
Всякий раз, когда вы выполняете I/O с файлом в 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"; Однако, если достижение EOF является ожидаемым и нормальным событием, вы не хотите завершать работу просто потому, что у вас закончился ввод. Вместо этого, вы, вероятно, хотите просто выйти из цикла ввода. Затем вы можете проверить, произошла ли ошибка, приведшая к завершению цикла, и действовать соответственно:
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 не сможет узнать, какой из множества возможных форматов текстового файла у вас есть, и не будет знать, как правильно отобразить данные из файла в символы, с которыми он может работать. Другие распространённые форматы кодировки включают "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.30.3/perlopentut