PerlIO
СОДЕРЖАНИЕ
ИМЯ
PerlIO — загрузчик по требованию для слоев PerlIO и корень пространства имён PerlIO::*
СИНОПСИС
# support platform-native and CRLF text files
open(my $fh, "<:crlf", "my.txt") or die "open failed: $!";
# append UTF-8 encoded text
open(my $fh, ">>:encoding(UTF-8)", "some.log")
or die "open failed: $!";
# portably open a binary file for reading
open(my $fh, "<", "his.jpg") or die "open failed: $!";
binmode($fh) or die "binmode failed: $!";
Shell:
PERLIO=:perlio perl .... ОПИСАНИЕ
Когда в спецификации слоев open или binmode встречается неопределённый слой 'foo', C-код выполняет эквивалент:
use PerlIO 'foo'; Код Perl в PerlIO.pm затем пытается найти слой, выполняя
require PerlIO::foo; В противном случае пакет PerlIO является местом для дополнительных функций, связанных с PerlIO.
Слои
В общем случае, слои PerlIO (ранее иногда называвшиеся «дисциплинами») представляют собой упорядоченную стопку, применяемую к дескриптору файла (указанному как список, разделённый пробелами или двоеточиями, обычно с ведущим двоеточием). Каждый слой выполняет некоторую операцию над любым входом или выходом, за исключением случаев, когда он пропускается, например, с sysread или syswrite. Операции чтения проходят по стопке в порядке их установки (слева направо), а операции записи — в обратном порядке.
Также существуют слои, которые просто устанавливают флаги в нижних слоях или слои, которые изменяют текущую стопку, но не сохраняются в ней сами; они называются псевдослоями.
При открытии дескриптора он будет открыт со всеми явно указанными слоями в вызове open() (или значениями по умолчанию платформы, если они указаны двоеточием без последующих слоёв).
Если слои не указаны явно, дескриптор будет открыт со слоями, указанными в переменной ${^OPEN} (обычно устанавливается с помощью псевдонима open для лексического области видимости или переключателя командной строки -C или переменной окружения PERL_UNICODE для области видимости основной программы).
Если слои не указаны в вызове open() или в переменной ${^OPEN}, дескриптор будет открыт со слоем стека, настроенным по умолчанию для данной архитектуры; см. "Значения по умолчанию и как их переопределить".
Некоторые слои автоматически вставляют необходимые нижние слои, если они отсутствуют; например, :perlio вставит :unix ниже себя для низкоуровневого ввода-вывода, а :encoding вставит значения по умолчанию платформы для буферизованного ввода-вывода.
Функция binmode может быть вызвана с открытым дескриптором, чтобы добавить дополнительные слои в стопку, которые также могут изменить существующие слои. Вызов binmode без слоев удалит или сбросит все существующие слои, которые преобразуют поток байтов, сделав дескриптор подходящим для бинарных данных.
В настоящее время определены следующие слои:
- :unix
-
Низкоуровневый слой, который предоставляет базовые операции PerlIO в терминах вызовов числового дескриптора файла UNIX/POSIX (open(), read(), write(), lseek(), close()). Он используется даже на не-UNIX архитектурах, и большинство других слоев работают поверх него.
- :stdio
-
Слой, который вызывает
fread,fwriteиfseek/ftellи т. д. Обратите внимание, что поскольку это «реальный» stdio, он игнорирует любые слои ниже него и сразу переходит к операционной системе через библиотеку C, как обычно. Этот слой реализует как низкоуровневый ввод-вывод, так и буферизацию, но на современных архитектурах используется редко. - :perlio
-
Реализация буферизации PerlIO с нуля. Предоставляет быстрый доступ к буферу для
sv_gets, который реализует Perl's readline/<> и в целом пытается минимизировать копирование данных.:perlioвставит слой:unixниже себя, чтобы выполнить низкоуровневый ввод-вывод. - :crlf
-
Слой, который реализует окончания строк DOS/Windows типа CRLF. При чтении преобразует пары CR,LF в один символ новой строки «\n». При записи преобразует каждую «\n» в пару CR,LF. Обратите внимание, что этот слой молча откажется от помещения поверх себя.
В настоящее время он не имитирует MS-DOS, что касается обработки Control-Z как маркера конца файла.
На архитектурах типа DOS/Windows, где этот слой является частью значений по умолчанию, он также действует как слой
:perlio, и удаление преобразования CRLF (например, с помощью:raw) удалит только флаг преобразования CRLF. Начиная с Perl 5.14, вы также можете применить другой слой:crlf, например, когда преобразование CRLF должно произойти после слоя кодирования. На других архитектурах это обычный слой преобразования CRLF, и его можно добавлять и удалять обычно.# translate CRLF after encoding on Perl 5.14 or newer binmode $fh, ":raw:encoding(UTF-16LE):crlf" or die "binmode failed: $!"; - :utf8
-
Псевдослой, который объявляет, что поток принимает улучшенную кодировку символов Perl, которая примерно соответствует UTF-8 на машинах ASCII, но UTF-EBCDIC на машинах EBCDIC. Это позволяет читать или записывать в поток любой символ, который может представлять Perl.
Этот слой (который фактически устанавливает флаг на предыдущем слое и неявно устанавливается любым слоем
:encoding) не преобразует и не проверяет последовательности байтов. Вместо этого он указывает, что поток байтов будет организован другими слоями, чтобы быть предоставленным во внутренней улучшенной кодировке Perl, которую код Perl (и правильно написанный XS-код) будет интерпретировать как декодированные символы Юникода.ВНИМАНИЕ: Не используйте этот слой для преобразования из UTF-8 байтов, так как неверные UTF-8 или двоичные данные приведут к неправильным строкам Perl. Вероятно, он не создаст неверный UTF-8 при использовании для вывода, хотя вместо этого он создаст UTF-EBCDIC на системах EBCDIC. Слой
:encoding(UTF-8)(дефис имеет значение) предпочтительнее, так как он гарантирует преобразование между допустимыми UTF-8 байтами и допустимыми символами Юникода. - :bytes
-
Это обратный псевдослой
:utf8. Он отключает флаг в нижнем слое, поэтому данные, считанные из него, рассматриваются как внутренняя пониженная кодировка Perl, таким образом, интерпретируемая как родная однобайтовая кодировка Latin-1 или EBCDIC. Точно так же при выводе Perl будет предупреждать, если символ «шириной» (код символа, не входящий в диапазон 0..255) будет записан в такой поток.Это очень опасно добавлять в дескриптор с помощью слоя
:encoding, так как такой слой предполагает работу с улучшенной внутренней кодировкой Perl, поэтому вы, скорее всего, получите повреждённый результат. Вместо этого используйте:rawили:pop, чтобы удалить слои кодирования. - :raw
-
Псевдослой
:rawопределяется как идентичный вызовуbinmode($fh)— поток подготавливается для передачи двоичных данных, то есть каждый байт передаётся как есть. Поток всё ещё будет буферизован (но это не всегда было верно до Perl 5.14).В Perl 5.6 и некоторых книгах слой
:rawдокументируется как обратный слою:crlf. Это больше не так — другие слои, которые могли бы изменить двоичный характер потока, также отключаются. Если вы хотите окончания строк UNIX на платформе, которая обычно использует CRLF-преобразование, но всё ещё хотите UTF-8 или значения по умолчанию кодирования, следует добавить:perlioв переменную окружения PERLIO или явно открыть дескриптор с этим слоем, чтобы заменить значение по умолчанию платформы:crlf.Реализация
:raw— это псевдослой, который, при «добавлении», извлекает себя и затем любые слои, которые могли бы изменить двоичный поток данных. (Отмена:utf8и:crlfможет быть реализована с помощью очистки флагов, а не извлечения слоёв, но это реализация деталей.)Вследствие того, что
:rawобычно извлекает слои, обычно он имеет смысл только как единственный или первый элемент в спецификации слоя. При использовании в качестве первого элемента он предоставляет известную базу для построения, например:open(my $fh,">:raw:encoding(UTF-8)",...) or die "open failed: $!";будет строить «бинарный» поток независимо от значений по умолчанию платформы, но затем включит преобразование UTF-8.
- :pop
-
Псевдослой, который удаляет самый верхний слой. Предоставляет коду Perl способ манипулировать стеком слоёв. Обратите внимание, что
:popработает только со реальными слоями и не отменит действия псевдослоев или флагов, таких как:utf8. Пример возможного использования:open(my $fh,...) or die "open failed: $!"; ... binmode($fh,":encoding(...)") or die "binmode failed: $!"; # next chunk is encoded ... binmode($fh,":pop") or die "binmode failed: $!"; # back to un-encodedНеобходимо более элегантное (и безопасное) интерфейс.
Пользовательские слои
Возможна разработка пользовательских слоёв помимо встроенных, как в C/XS, так и в Perl, в виде модуля, названного PerlIO::<layer name>. Некоторые пользовательские слои входят в состав дистрибутива Perl.
- :encoding
-
Используйте
:encoding(ENCODING)для прозрачного преобразования наборов символов и кодировок, например, от Shift-JIS к Юникоду. Обратите внимание, что:encodingтакже включает:utf8. См. PerlIO::encoding для получения дополнительной информации. - :mmap
-
Слой, который реализует «чтение» файлов путём использования
mmap()для отображения (всего) файла в адресном пространстве процесса, а затем использования этого в качестве «буфера» PerlIO. Это может быть быстрее в определённых случаях для больших файлов и может привести к меньшему использованию физической памяти, когда несколько процессов читают один и тот же файл.Файлы, которые не поддерживают
mmap(), ведут себя как слой:perlio. Записи также ведут себя как слой:perlio, так какmmap()для записи требует дополнительных действий (расширения файла), что сводит на нет любое преимущество.Слой
:mmapне будет существовать, если платформа не поддерживаетmmap(). См. PerlIO::mmap для получения дополнительной информации. - :via
-
:via(MODULE)позволяет применять преобразование произвольным модулем Perl, например, сжатие/распаковка, шифрование/дешифрование. См. PerlIO::via для получения дополнительной информации. - :scalar
-
Слой, реализующий «в памяти» файлы, использующие переменные скаляров, автоматически используемые вместо значений по умолчанию платформы для ввода-вывода при открытии такого дескриптора. Таким образом, скаляр должен действовать как файл, содержащий или хранящий байты. См. PerlIO::scalar для получения дополнительной информации.
Альтернативы raw
Для получения двоичного потока можно использовать альтернативный метод:
open(my $fh,"<","whatever") or die "open failed: $!";
binmode($fh) or die "binmode failed: $!"; Это имеет преимущество обратной совместимости со старыми версиями Perl, которые не использовали PerlIO или где :raw было неисправным (так как это было до Perl 5.14).
Для получения потока без буферизации укажите слой без буферизации (например, :unix) в вызове open:
open(my $fh,"<:unix",$path) or die "open failed: $!"; Значения по умолчанию и как их переопределить
Если платформа похожа на MS-DOS и обычно выполняет перевод CRLF в "\n" для текстовых файлов, то значения по умолчанию:
:unix:crlf В противном случае, если Configure обнаружил способ выполнения "быстрого" ввода-вывода с помощью системного stdio (не часто встречается на современных архитектурах), то значения по умолчанию:
:stdio В противном случае значения по умолчанию:
:unix:perlio Обратите внимание, что "стек по умолчанию" зависит от операционной системы и версии Perl, а также от конфигураций Perl во время компиляции и выполнения. Значение по умолчанию можно переопределить, установив переменную окружения PERLIO в список слоёв, разделённых пробелами или двоеточиями. Однако это нельзя использовать для установки слоёв, требующих загрузки модулей, таких как :encoding.
Это можно использовать для просмотра эффекта/ошибок в различных слоях, например:
cd .../perl/t
PERLIO=:stdio ./perl harness
PERLIO=:perlio ./perl harness Для различных значений PERLIO см. "PERLIO" в perlrun.
В следующей таблице обобщены значения по умолчанию для слоёв на платформах типа UNIX и DOS, в зависимости от значения $ENV{PERLIO}.
PERLIO UNIX-like DOS-like
------ --------- --------
unset / "" :unix:perlio / :stdio [1] :unix:crlf
:stdio :stdio :stdio
:perlio :unix:perlio :unix:perlio
# [1] ":stdio" if Configure found out how to do "fast stdio" (depends
# on the stdio implementation) and in Perl 5.8, else ":unix:perlio" Получение информации о слоях файловых дескрипторов
Следующее возвращает имена слоёв PerlIO для файлового дескриптора.
my @layers = PerlIO::get_layers($fh); # Or FH, *FH, "FH". Слои возвращаются в порядке, в котором их использует вызов open() или binmode(), и без двоеточий.
По умолчанию возвращаются слои со стороны входного потока файлового дескриптора. Для получения слоёв со стороны выходного потока используйте необязательный аргумент output.
my @layers = PerlIO::get_layers($fh, output => 1); (Обычно слои одинаковы с обеих сторон файлового дескриптора, но, например, в случае с сокетами могут быть различия.)
Нет функции set_layers(), и get_layers() не возвращает связанный массив, отображающий стек, или что-то подобное. Это не случайно и не преднамеренно. Стек слоёв PerlIO немного сложнее, чем просто стек (см., например, поведение :raw). Предполагается, что для управления стеком будут использоваться open() и binmode().
Следующая информация — детали реализации. Закройте глаза.
Аргументы слоёв по умолчанию возвращаются в скобках после имени слоя, и некоторые слои (например, :utf8) не являются реальными слоями, а представляют собой флаги на реальных слоях. Для получения всех этих элементов отдельно используйте необязательный аргумент details.
my @layer_and_args_and_flags = PerlIO::get_layers($fh, details => 1); Результат будет втрое больше количества слоёв: первый элемент — имя, второй — аргументы (неуказанные аргументы будут undef), третий — флаги, четвёртый — имя и так далее.
Теперь вы можете открыть глаза.
АВТОР
Nick Ing-Simmons <nick@ing-simmons.net>
См. также
"binmode" в perlfunc, "open" в perlfunc, perlunicode, perliol, Encode
© 1993–2023 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.38.0/PerlIO