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 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) будет интерпретировать как декодированные символы Unicode.ВНИМАНИЕ: Не используйте этот слой для преобразования из UTF-8 байтов, так как недействительные UTF-8 или двоичные данные приведут к некорректным строкам Perl. Хотя при выводе он вряд ли создаст недействительный UTF-8, вместо этого он создаст UTF-EBCDIC на системах EBCDIC. Слой
:encoding(UTF-8)(дефис важен) предпочтительнее, так как он гарантирует преобразование между допустимыми UTF-8 байтами и допустимыми символами Unicode. - :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 к 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 для получения дополнительной информации.
Альтернативы 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–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.36.0/PerlIO