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 .... ОПИСАНИЕ
Когда встречается неопределённый слой «foo» в спецификации слоёв open или binmode, код 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
-
Слой, который реализует окончания строк CRLF, как в DOS/Windows. При чтении преобразует пары 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Необходим более элегантный (и безопасный) интерфейс.
- :win32
-
На платформах Win32 этот экспериментальный слой использует родной ввод-вывод «дескриптора» вместо слоя числового дескриптора файла, похожего на UNIX. Известно, что он содержит ошибки по состоянию на Perl 5.8.2.
Пользовательские слои
Можно написать пользовательские слои в дополнение к встроенным, как на C/XS, так и на Perl, в виде модуля PerlIO::<layer name>. Некоторые пользовательские слои поставляются с дистрибутивом Perl.
- :encoding
-
Используйте
:encoding(ENCODING)для прозрачного выполнения преобразований кодировки символов, например, от Shift-JIS к Unicode. Обратите внимание, что:encodingтакже активирует:utf8. Для получения дополнительной информации см. PerlIO::encoding. - :mmap
-
Слой, который реализует «чтение» файлов, используя
mmap()для отображения (всего) файла в адресном пространстве процесса, а затем использование этого как «буфера» PerlIO. В некоторых случаях это может быть быстрее для больших файлов и может привести к меньшему использованию физической памяти, когда несколько процессов читают один и тот же файл.Файлы, которые не поддерживают
mmap()возвращаются к поведению слоя:perlio. Записи также ведут себя как слой:perlio, так какmmap()для записи требует дополнительного управления (для расширения файла), что сводит на нет любое преимущество.Слой
:mmapне будет существовать, если платформа не поддерживаетmmap(). Для получения дополнительной информации см. PerlIO::mmap. - :via
-
:via(MODULE)позволяет применять преобразование с помощью произвольного Perl-модуля, например, сжатие/распаковка, шифрование/дешифрование. Для получения дополнительной информации см. PerlIO::via. - :scalar
-
Слой, реализующий файлы «в памяти» с использованием переменных скаляров, автоматически используемый вместо системных значений по умолчанию для ввода-вывода при открытии такого дескриптора. Таким образом, скаляр должен действовать как файл, содержащий или хранящий только байты. Для получения дополнительной информации см. PerlIO::scalar.
Альтернативы необработанному вводу-выводу
Для получения двоичного потока можно использовать альтернативный метод:
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–2021 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.34.0/PerlIO