Spec-Zone.ru › Perl 5.38

PerlIO

СОДЕРЖАНИЕ

  • ИМЯ
  • СИНОПСИС
  • ОПИСАНИЕ
    • Слои
    • Пользовательские слои
    • Альтернативы raw
    • Значения по умолчанию и как их переопределить
    • Запрос слоев дескрипторов файлов
  • АВТОР
  • СМОТРИТЕ ТАКЖЕ

ИМЯ

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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API