Spec-Zone.ru › Perl 5.34

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 ....

ОПИСАНИЕ

Когда встречается неопределённый слой «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

Spec-Zone.ru

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