Storable
СОДЕРЖАНИЕ
- ИМЯ
- СИНТАКСИС
- ОПИСАНИЕ
- ХРАНЕНИЕ В ПАМЯТИ
- КОНСУЛЬТАТИВНАЯ БЛОКИРОВКА
- СКОРОСТЬ
- КАНОНИЧЕСКОЕ ПРЕДСТАВЛЕНИЕ
- ССЫЛКИ НА КОД
- ВЕРСИОННАЯ СОСТОЯТЕЛЬНОСТЬ
- ОТОБРАЖЕНИЕ ОШИБОК
- ТОЛЬКО ДЛЯ МАСТЕРОВ
- Магия Storable
- ПРИМЕРЫ
- ПРЕДУПРЕЖДЕНИЕ О БЕЗОПАСНОСТИ
- ПРЕДУПРЕЖДЕНИЕ
- РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ
- ОШИБКИ
- АВТОРЫ
- АВТОР
- СМОТРИТЕ ТАКЖЕ
ИМЯ
Storable - сохранение структур данных Perl
СИНТАКСИС
use Storable;
store \%table, 'file';
$hashref = retrieve('file');
use Storable qw(nstore store_fd nstore_fd freeze thaw dclone);
# Network order
nstore \%table, 'file';
$hashref = retrieve('file'); # There is NO nretrieve()
# Storing to and retrieving from an already opened file
store_fd \@array, \*STDOUT;
nstore_fd \%table, \*STDOUT;
$aryref = fd_retrieve(\*SOCKET);
$hashref = fd_retrieve(\*SOCKET);
# Serializing to memory
$serialized = freeze \%table;
%table_clone = %{ thaw($serialized) };
# Deep (recursive) cloning
$cloneref = dclone($ref);
# Advisory locking
use Storable qw(lock_store lock_nstore lock_retrieve)
lock_store \%table, 'file';
lock_nstore \%table, 'file';
$hashref = lock_retrieve('file'); ОПИСАНИЕ
Пакет Storable обеспечивает сохранение ваших структур данных Perl, содержащих SCALAR, ARRAY, HASH или REF объекты, то есть всё, что удобно хранить на диске и извлекать позже.
Он может использоваться обычным процедурным способом, вызывая store со ссылкой на объект, который нужно сохранить, вместе с именем файла, куда должно быть записано изображение.
Процедура возвращает undef при проблемах с ВВОД/ВЫВОД или других внутренних ошибках, в противном случае — истинное значение. Серьёзные ошибки распространяются как исключение die.
Для извлечения данных, сохранённых на диске, используйте retrieve с именем файла. Сохранённые в этом файле объекты регенерируются в памяти, и возвращается ссылка на корневой объект. В случае ошибки ввода/вывода при чтении возвращается undef. Другие серьёзные ошибки распространяются через die.
Поскольку хранение выполняется рекурсивно, вы можете поместить ссылки на объекты, которые разделяют много общих данных, в один массив или хеш-таблицу, а затем сохранить этот объект. Таким образом, при извлечении всего объекта, объекты будут по-прежнему разделять то, что они изначально разделяли.
За счёт небольшого накладных расходов заголовка вы можете сохранять в уже открытый дескриптор файла, используя функцию store_fd, и извлекать из файла через fd_retrieve. Эти имена не импортируются по умолчанию, поэтому вам нужно будет сделать это явно, если вам нужны эти функции. Дескриптор файла, который вы предоставляете, должен быть уже открыт, для чтения, если вы собираетесь извлекать данные, и для записи, если вы хотите их сохранить.
store_fd(\%table, *STDOUT) || die "can't store to stdout\n";
$hashref = fd_retrieve(*STDIN); Вы также можете сохранять данные в сетевом порядке для лёгкого обмена между различными платформами или при сохранении на сокете, который известно подключён удалённо. Функции для вызова имеют начальный префикс n для сетевых операций, как в nstore и nstore_fd. При извлечении данные будут правильно восстановлены, поэтому вам не нужно знать, извлекаете ли вы данные из исходного или сетевого порядка. Двойные значения хранятся в строковом формате для обеспечения переносимости, с небольшим риском потери точности в последних десятичных разрядах.
При использовании fd_retrieve, объекты извлекаются последовательно, по одному объекту (т.е. по одному рекурсивному дереву) на ассоциированный store_fd.
Если вы больше из лагеря объектно-ориентированного программирования, вы можете унаследовать от Storable и напрямую сохранить свои объекты, вызвав store в качестве метода. Тот факт, что корень дерева, которое нужно сохранить, является освященной ссылкой (т.е. объектом), является особым случаем, чтобы извлечение не предоставляло ссылку на этот объект, а ссылку на сам освящённый объект. (В противном случае вы бы получили ссылку на этот освящённый объект).
ХРАНЕНИЕ В ПАМЯТИ
Двигатель Storable также может сохранять данные в скаляр Perl, чтобы позже их извлечь. Это в основном используется для заморозки сложной структуры в некотором безопасном компактном месте памяти (где она потенциально может быть отправлена другому процессу через IPC, поскольку заморозка структуры фактически сериализует её). Позже, возможно, где-то в другом месте, вы можете разморозить скаляр Perl и воссоздать исходную сложную структуру в памяти.
Удивительно, но вызываемые функции называются freeze и thaw. Если вы хотите отправить замороженный скаляр на другой компьютер, используйте nfreeze вместо этого, чтобы получить переносимое изображение.
Обратите внимание, что заморозка структуры объекта и её немедленное оттаивание фактически достигает глубокого клонирования этой структуры:
dclone(.) = thaw(freeze(.)) Storable предоставляет вам интерфейс dclone, который не создаёт этот промежуточный скаляр, а вместо этого замораживает структуру в некотором внутреннем пространстве памяти, а затем сразу же размораживает её.
КОНСУЛЬТАТИВНАЯ БЛОКИРОВКА
Функции lock_store и lock_nstore эквивалентны store и nstore, за исключением того, что они получают эксклюзивную блокировку файла перед записью. Аналогично, lock_retrieve делает то же самое, что и retrieve, но также получает общую блокировку файла перед чтением.
Как и в любой схеме консультативной блокировки, защита работает только в том случае, если вы систематически используете lock_store и lock_retrieve. Если одна сторона вашего приложения использует store, а другая lock_retrieve, никакой защиты не будет.
Внутренняя консультативная блокировка реализована с помощью функции flock() Perl. Если ваша система не поддерживает какую-либо форму flock(), или если вы делитесь своими файлами через NFS, вам может потребоваться использовать другие типы блокировки, используя модули, такие как LockFile::Simple, который блокирует файл с помощью записи в файловой системе, вместо блокировки дескриптора файла.
СКОРОСТЬ
Ядро Storable написано на C для обеспечения достойной скорости. Были произведены дополнительные оптимизации низкого уровня при манипулировании внутренними элементами Perl, чтобы пожертвовать инкапсуляцией в пользу большей скорости.
КАНОНИЧЕСКОЕ ПРЕДСТАВЛЕНИЕ
Обычно Storable сохраняет элементы хешей в том порядке, в котором они хранятся внутри Perl, то есть псевдослучайно. Если вы установите $Storable::canonical на некоторое значение TRUE, Storable будет сохранять хеши с отсортированными по ключу элементами. Это позволяет вам сравнивать структуры данных путём сравнения их замороженных представлений (или даже сжатых замороженных представлений), что может быть полезно для создания таблиц поиска для сложных запросов.
Канонический порядок не подразумевает сетевой порядок; это два ортогональных параметра.
ССЫЛКИ НА КОД
Начиная с версии Storable 2.05, ссылки на CODE могут быть сериализованы с помощью B::Deparse. Для активации этой функции необходимо установить $Storable::Deparse в истинное значение. Для активации десериализации необходимо установить $Storable::Eval в истинное значение. Имейте в виду, что десериализация выполняется через eval, что опасно, если файл Storable содержит вредоносные данные. Вы можете установить $Storable::Eval на ссылку на подпрограмму, которая будет использоваться вместо eval. См. пример ниже, используя отсек Safe для десериализации ссылок на CODE.
Если $Storable::Deparse и/или $Storable::Eval установлены в ложные значения, то значение $Storable::forgive_me (см. ниже) соблюдается во время сериализации и десериализации.
ВЕРСИОННАЯ СОСТОЯТЕЛЬНОСТЬ
Эта версия Storable может использоваться в более новых версиях Perl для сериализации данных, которые не поддерживаются более ранними версиями Perl. По умолчанию Storable попытается сделать правильный выбор, при croak() в случае обнаружения данных, которые он не может десериализовать. Однако настройки по умолчанию можно изменить следующим образом:
- данные utf8
-
Perl 5.6 добавил поддержку символов Юникода с кодовыми точками > 255, а Perl 5.8 полностью поддерживает символы Юникода в ключах хешей. Perl внутренне кодирует строки с этими символами с помощью utf8, а Storable сериализует их как utf8. По умолчанию, если более старая версия Perl встречает значение utf8, которое она не может представить, она
croak(). Чтобы изменить это поведение, чтобы Storable десериализовывал закодированные в utf8 значения как строку байтов (эффективно удаляя флаг is_utf8), установите$Storable::drop_utf8на некотороеTRUEзначение. Это форма потери данных, потому что при$drop_utf8true становится невозможно определить, были ли исходные данные строкой Юникода или последовательностью байтов, которые оказываются валидным utf8. - ограниченные хеши
-
Perl 5.8 добавляет поддержку ограниченных хешей, ключи которых ограничены заданным набором, а значения могут быть заблокированы для чтения только для чтения. По умолчанию, когда Storable встречает ограниченный хеш на Perl, который их не поддерживает, он десериализует его как обычный хеш, молча игнорирует любые заполнительные ключи и оставляет ключи и все значения разблокированными. Чтобы Storable
croak()вместо этого, установите$Storable::downgrade_restrictedнаFALSEзначение. Чтобы восстановить значения по умолчанию, установите его на некотороеTRUEзначение.Стратегия хешей cperl PERL_PERTURB_KEYS_TOP имеет известную проблему с ограниченными хешами.
- большие объекты
-
В 64-битных системах некоторые структуры данных могут превышать лимит 2Гб (т. е. I32_MAX). В 32-битных системах также строки между I32 и U32 (2Гб-4Гб). Начиная со Storable 3.00 (не в ядре perl5) мы можем хранить и извлекать эти объекты, даже если сам perl5 не может с ними справиться. Это строки длиннее 4Гб, массивы с более чем 2Гб элементов и хеши с более чем 2Гб элементов. cperl запрещает хеши с более чем 2Гб элементов, но в cperl это приводит к ошибке. Сам perl5, по крайней мере до версии 5.26, позволяет это, но не может итерировать по ним. Обратите внимание, что создание таких объектов может вызвать исключения из-за недостатка памяти операционной системой, прежде чем perl успеет прервать процесс.
- файлы из будущих версий Storable
-
Более ранние версии Storable сразу же генерировали ошибку, если они встречали файл с номером внутренней версии, большим, чем у читающего Storable. Номера внутренних версий увеличиваются каждый раз, когда к словарю формата файла добавляются новые типы данных (например, ограниченные хеши). Это означало, что новый модуль Storable не мог записать файл, читаемый более старой версией Storable, даже если писатель не сохранял новые типы данных.
Эта версия Storable отложит генерацию ошибки до тех пор, пока не встретит тип данных в файле, который она не распознает. Это означает, что она будет продолжать читать файлы, сгенерированные более новыми модулями Storable, которые осторожны в том, что они записывают, что облегчает обновление модулей Storable в смешанной среде.
Старое поведение немедленной генерации ошибки может быть восстановлено путем установки
$Storable::accept_future_minorна некотороеFALSEзначение.
Все эти переменные не влияют на более новые версии Perl, которые поддерживают соответствующую функцию.
ОТЧЕТ ОБ ОШИБКАХ
Storable использует парадигму «исключение», в том смысле, что не пытается обойти сбои: если произойдет что-то плохое, генерируется исключение с точки зрения вызывающей стороны (см. Carp и croak()). Используйте eval {}, чтобы перехватить эти исключения.
Когда Storable генерирует ошибку, он пытается сообщить об ошибке через процедуру logcroak() из пакета Log::Agent, если она доступна.
Обычные ошибки сообщаются путем возврата store() или retrieve() undef. Такие ошибки обычно являются ошибками ввода-вывода (или ошибками усеченных потоков при извлечении).
Когда Storable выбрасывает ошибку «Превышена максимальная глубина рекурсии со вложенными структурами», у нас уже закончилось пространство стека. К сожалению, в некоторых более ранних версиях perl очистка рекурсивной структуры данных приводит к рекурсии в вызовах освобождения, что приведет к переполнению стека при очистке. Эта структура данных затем не очищается должным образом, она будет уничтожена только во время глобального уничтожения.
ТОЛЬКО ДЛЯ ЭКСПЕРТОВ
Обработчики
Любой класс может определить обработчики, которые будут вызываться во время процесса сериализации и десериализации объектов, являющихся экземплярами этого класса. Эти обработчики могут переопределять способ выполнения сериализации (и, следовательно, как должна проводиться симметричная десериализация).
Так как мы ранее сказали:
dclone(.) = thaw(freeze(.)) все, что мы говорим об обработчиках, также должно относиться к глубокому клонированию. Однако обработчики узнают, является ли операция простой сериализацией или клонированием.
Поэтому, при вовлечении обработчиков сериализации,
dclone(.) <> thaw(freeze(.)) Ну, вы могли бы поддерживать их синхронизацию, но нет гарантии, что это всегда будет выполняться для классов, написанных другими людьми. Кроме того, пользы в этом мало: обработчик сериализации может сохранить только один атрибут объекта, что, вероятно, не должно происходить при глубоком клонировании этого же объекта.
Вот интерфейс обработчиков:
-
STORABLE_freezeobj, cloning -
Обработчик сериализации, вызываемый для объекта во время сериализации. Он может наследоваться или определяться в самом классе, как и любой другой метод.
Аргументы: obj — объект для сериализации, cloning — флаг, указывающий, находимся ли мы в dclone() или в обычной сериализации через store() или freeze().
Возвращаемое значение: СПИСОК
($serialized, $ref1, $ref2, ...)где $serialized — сериализованная форма, которая будет использоваться, а необязательные $ref1, $ref2 и т. д. — дополнительные ссылки, которые вы хотите позволить двигателю Storable сериализовать.Во время десериализации вам будет возвращен тот же СПИСОК, но все дополнительные ссылки будут указывать на десериализованную структуру.
В первый раз обработчик срабатывает в потоке сериализации, вы можете вернуть пустой список. Это укажет движку Storable на дальнейшее отбрасывание этого обработчика для данного класса и, следовательно, возвращение к стандартной сериализации базовых данных Perl. Обработчик будет обработано по-новому в следующей сериализации.
Если вы не знаете лучше, обработчик сериализации всегда должен возвращать:
sub STORABLE_freeze { my ($self, $cloning) = @_; return if $cloning; # Regular default serialization .... }чтобы сохранить разумную семантику dclone().
-
STORABLE_thawobj, cloning, serialized, ... -
Обработчик десериализации, вызываемый для объекта во время десериализации. Но подождите: если мы десериализуем, то объекта еще нет… верно?
Неверно: движок Storable создает для вас пустой. Если вы знаете Eiffel, вы можете рассматривать
STORABLE_thawкак альтернативную процедуру создания.Это означает, что обработчик может наследоваться как любой другой метод, и что obj — ваша освященная ссылка для этого конкретного экземпляра.
Другие аргументы должны быть вам знакомы, если вы знаете
STORABLE_freeze: cloning — true, когда мы участвуем в операции глубокого клонирования, serialized — сериализованная строка, которую вы вернули движку вSTORABLE_freeze, и может быть необязательный список ссылок в том же порядке, в котором вы их предоставили во время сериализации, указывающие на десериализованные объекты (которые были обработаны движком Storable).Если движок Storable не находит обработчик
STORABLE_thaw, он пытается загрузить класс путем динамического требования пакета (используя имя освященного пакета) и затем повторно пытается найти обработчик. Если в этот момент обработчик не найден, движок генерирует ошибку. Обратите внимание, что эта механика потерпит неудачу, если вы определите несколько классов в одном файле, но perlmod предупреждал вас об этом.Вам решать, как использовать эту информацию для заполнения obj нужным вам образом.
Возвращаемое значение: ничего.
-
STORABLE_attachclass, cloning, serialized -
В то время как
STORABLE_freezeиSTORABLE_thawполезны для классов, где каждый экземпляр независим, эта механика имеет трудности (или несовместима) с объектами, которые существуют как общие ресурсы уровня процесса или системы, такие как одиночные объекты, пулы баз данных, кэши или кешированные объекты.Альтернативный метод
STORABLE_attachпредоставляет решение для этих общих объектов. ВместоSTORABLE_freeze-->STORABLE_thaw, вы реализуетеSTORABLE_freeze-->STORABLE_attachвместо этого.Аргументы: class — класс, которому мы прикрепляем, cloning — флаг, указывающий, находимся ли мы в dclone() или в обычной десериализации через thaw(), а serialized — сохраненная строка для ресурсного объекта.
Поскольку эти ресурсные объекты считаются принадлежащими всему процессу/системе, а не «собственностью» того, что сериализуется, ссылки под объектом не должны включаться в сериализованную строку. Таким образом, в любом классе, реализующем
STORABLE_attach, методSTORABLE_freezeне может возвращать ссылки, аStorableсгенерирует ошибку, еслиSTORABLE_freezeпопытается вернуть ссылки.Вся информация, необходимая для «прикрепления» обратно к общему ресурсному объекту, должна быть содержаться только в возвращаемой строке
STORABLE_freeze. В противном случаеSTORABLE_freezeведет себя как обычно дляSTORABLE_attachклассов.Поскольку
STORABLE_attachполучает класс (а не объект), он также возвращает объект напрямую, а не изменяет переданный объект.Возвращаемое значение: объект типа
class
Предикаты
Предикаты не экспортируются. Они должны вызываться путем явного добавления имени пакета Storable.
-
Storable::last_op_in_netorder -
Предикат
Storable::last_op_in_netorder()скажет вам, использовался ли сетевой порядок в последней операции store или retrieve. Если вы не знаете, как это использовать, просто забудьте об этом. -
Storable::is_storing -
Возвращает true, если выполняется операция store (через обработчик STORABLE_freeze).
-
Storable::is_retrieving -
Возвращает true, если выполняется операция retrieve (через обработчик STORABLE_thaw).
Рекурсия
Обработчики предоставляют возможность рекурсивного возврата к движку Storable. Действительно, обработчики — это обычный Perl-код, и Storable удобен, когда дело доходит до сериализации и десериализации вещей, так зачем не использовать его для обработки сериализованной строки?
Однако есть несколько моментов, которые следует знать:
-
От Storable 3.05 до 3.13 мы проверяли предел рекурсии стека для ссылок, массивов и хэшей до максимальной глубины ~1200-35000, иначе мы могли попасть в переполнение стека. В JSON::XS этот предел составляет 512. Если ссылки не ссылаются друг на друга непосредственно, такого ограничения пока нет, поэтому вы можете столкнуться с переполнением стека и segfault.
У этой проверки и выполненных нами проверок есть некоторые ограничения:
-
размер стека во время компиляции может отличаться от размера стека во время выполнения, например, размер стека может быть изменён с помощью ulimit(1). Если он больше во время выполнения, Storable может излишне прервать freeze() или thaw(). Если он больше во время компиляции, Storable может получить ошибку segmentation fault при обработке глубокой структуры во время выполнения.
-
размер стека может отличаться в потоке.
-
пределы рекурсии массивов и хэшей проверяются отдельно относительно той же глубины рекурсии, замороженная структура с большой последовательностью вложенных массивов внутри многих вложенных хэшей может исчерпать стек процессора, не вызвав защиту рекурсии Storable.
Поэтому теперь у них есть простые значения по умолчанию вместо проверки во время компиляции.
Вы можете контролировать максимальную глубину рекурсии массивов и хэшей, изменив
$Storable::recursion_limitи$Storable::recursion_limit_hashсоответственно. Любое из них можно установить в-1, чтобы предотвратить любые проверки глубины, хотя это не рекомендуется. -
-
Вы можете создать бесконечные циклы, если элементы, которые вы сериализуете с помощью freeze() (например), ссылаются обратно на объект, который мы пытаемся сериализовать в обработчике.
-
Общие ссылки между объектами не сохранятся: если мы сериализуем список объектов [A, C], где оба объекта A и C ссылаются на ОДИН и тот же объект B, и если есть обработчик сериализации в A, который говорит freeze(B), то при десериализации мы получим [A', C'], где A' ссылается на B', но C' ссылается на D, глубокую копию B'. Топология не сохранилась.
-
Максимальный предел рекурсии стека вашей системы возвращается
stack_depth()иstack_depth_hash(). Предел хэша обычно равен половине размера предела массива и ссылки, поскольку API Perl хэшей не является оптимальным.
Вот почему STORABLE_freeze позволяет предоставить список ссылок для сериализации. Движок гарантирует, что они будут сериализованы в том же контексте, что и другие объекты, а значит, что общие объекты останутся общими.
В примере выше [A, C] обработчик STORABLE_freeze мог бы вернуть:
("something", $self->{B}) и часть B была бы сериализована движком. В STORABLE_thaw, вы бы получили обратно ссылку на объект B', десериализованный для вас.
Поэтому рекурсию обычно следует избегать, но она всё же поддерживается.
Глубокое клонирование
На CPAN есть модуль Clone, который реализует глубокое клонирование напрямую, то есть без заморозки в памяти и разморозки результата. В будущем он должен заменить dclone() в Storable. Однако в настоящее время он не поддерживает обработчики Storable для переопределения способа выполнения глубокого клонирования.
Магия Storable
Да, этого много :-) Но точнее, в системах UNIX есть утилита file, которая распознаёт файлы данных по их содержимому (обычно по первым нескольким байтам). Для этого определённый файл под названием magic должен быть обучен сигнатуре данных. Где находится этот файл конфигурации, зависит от типа UNIX; часто это что-то вроде /usr/share/misc/magic или /etc/magic. Администратор системы должен обновить файл magic. Необходимая информация о сигнатуре выводится в стандартный вывод при вызове Storable::show_file_magic(). Обратите внимание, что GNU-реализация утилиты file, версия 3.38 или более поздняя, помимо других типов файлов Perl, должна по умолчанию поддерживать распознавание файлов Storable.
Вы также можете использовать следующие функции для извлечения информации о заголовке файла из изображений Storable:
- $info = Storable::file_magic( $filename )
-
Если данный файл является изображением Storable, возвращается хэш, описывающий его. Если файл читается, но не является изображением Storable, возвращается
undef. Если файл не существует или не читается, выдаётся ошибка.Возвращаемый хэш содержит следующие элементы:
version-
Это возвращает версию формата файла. Это строка, например, "2.7".
Обратите внимание, что это номер версии не совпадает с номером версии самого модуля Storable. Например, Storable v0.7 создаёт файлы в формате v2.0, а Storable v2.15 создаёт файлы в формате v2.7. Номер версии формата файла увеличивается только при добавлении новых функций, которые могут сбить с толку более старые версии модуля.
У файлов, более старых, чем v2.0, будет один из номеров версии "-1", "0" или "1". На тот момент не использовались второстепенные номера.
version_nv-
Это возвращает номер версии формата файла в виде числа. Это строка, например, "2.007". Это значение подходит для числового сравнения.
Функция-константа
Storable::BIN_VERSION_NVвозвращает сравнимое число, которое представляет наибольший номер версии файла, полностью поддерживаемый этой версией Storable (но см. обсуждение$Storable::accept_future_minorвыше). Функция-константаStorable::BIN_WRITE_VERSION_NVвозвращает номер версии файла, который записывается, и может быть меньше, чемStorable::BIN_VERSION_NVв некоторых конфигурациях. -
major,minor -
Это также возвращает номер версии формата файла. Если версия равна "2.7", то major будет 2, а minor будет 7. Элемент minor отсутствует, когда major меньше 2.
hdrsize-
Это количество байтов, занимаемых заголовком Storable.
netorder-
Это ИСТИНА, если изображение хранит данные в сетевом порядке. Это означает, что оно было создано с помощью nstore() или аналогичной функции.
byteorder-
Это присутствует только тогда, когда
netorderложно. Это строка $Config{byteorder} perl, который создал это изображение. Это строка, например, "1234" (32-битный little endian) или "87654321" (64-битный big endian). Это должно совпадать с текущим perl для того, чтобы изображение могло быть прочитано Storable. -
intsize,longsize,ptrsize,nvsize -
Они присутствуют только когда
netorderложно. Это размеры различных типов C данных perl, который создал это изображение. Они должны совпадать с текущим perl для того, чтобы изображение могло быть прочитано Storable.Элемент
nvsizeприсутствует только для формата файлов v2.2 и выше. file-
Имя файла.
- $info = Storable::read_magic( $buffer )
- $info = Storable::read_magic( $buffer, $must_be_file )
-
В $buffer должен быть образ Storable или первые несколько байтов его. Если $buffer начинается с заголовка Storable, возвращается хэш, описывающий изображение, в противном случае возвращается
undef.Хэш имеет такую же структуру, что и возвращаемый Storable::file_magic(). Элемент
fileравен ИСТИНА, если изображение является изображением файла.Если аргумент $must_be_file передан и равен ИСТИНА, то возвращается
undef, если изображение не похоже на дамп файла.Максимальный размер заголовка Storable в настоящее время составляет 21 байт. Если предоставленный $buffer представляет собой только часть изображения Storable, он должен иметь по крайней мере такую длину, чтобы гарантировать, что read_magic() распознает его как таковой.
ПРИМЕРЫ
Вот несколько примеров кода, показывающих возможное использование Storable:
use Storable qw(store retrieve freeze thaw dclone);
%color = ('Blue' => 0.1, 'Red' => 0.8, 'Black' => 0, 'White' => 1);
store(\%color, 'mycolors') or die "Can't store %a in mycolors!\n";
$colref = retrieve('mycolors');
die "Unable to retrieve from mycolors!\n" unless defined $colref;
printf "Blue is still %lf\n", $colref->{'Blue'};
$colref2 = dclone(\%color);
$str = freeze(\%color);
printf "Serialization of %%color is %d bytes long.\n", length($str);
$colref3 = thaw($str); что выводит (на моём компьютере):
Blue is still 0.100000
Serialization of %color is 102 bytes long. Сериализация ссылок CODE и десериализация в безопасном отсеке:
use Storable qw(freeze thaw);
use Safe;
use strict;
my $safe = new Safe;
# because of opcodes used in "use strict":
$safe->permit(qw(:default require));
local $Storable::Deparse = 1;
local $Storable::Eval = sub { $safe->reval($_[0]) };
my $serialized = freeze(sub { 42 });
my $code = thaw($serialized);
$code->() == 42; ПРЕДУПРЕЖДЕНИЕ О БЕЗОПАСНОСТИ
Не принимайте документы Storable из ненадежных источников!
Некоторые функции Storable могут привести к уязвимостям безопасности, если вы принимаете документы Storable из ненадежных источников с флагами по умолчанию. Наиболее очевидно, что необязательная (по умолчанию выключенная) функция сериализации ссылок CODE позволяет передавать код в процесс десериализации. Кроме того, любой сериализованный объект заставит Storable загрузить модуль, соответствующий классу объекта, в модуль десериализации. При манипулировании именами модулей это может загрузить почти произвольный код. Наконец, деструкторы десериализованного объекта будут вызваны, когда объекты будут уничтожены в процессе десериализации. Злонамеренно составленные документы Storable могут поместить такие объекты в значение ключа хэша, которое переопределяется другой парой ключ/значение в том же хэше, вызывая тем самым немедленное выполнение деструктора.
Чтобы отключить благословление объектов во время разморозки/получения, удалите флаг BLESS_OK = 2 из $Storable::flags или установите второй аргумент для thaw/retrieve в 0.
Чтобы отключить привязку данных во время разморозки/получения, удалите флаг TIE_OK = 4 из $Storable::flags или установите второй аргумент для thaw/retrieve в 0.
При значении $Storable::flags = 6 по умолчанию создание или уничтожение случайных объектов, даже переименованных объектов, может контролироваться злоумышленником. См. CVE-2015-1592 и его модуль metasploit.
Если ваше приложение требует приема данных из ненадежных источников, лучше всего использовать менее мощный и, скорее всего, безопасный формат сериализации и реализацию. Если ваши данные достаточно простые, Cpanel::JSON::XS, Data::MessagePack или Serial являются лучшим выбором и обеспечивают максимальную совместимость, но обратите внимание, что Serial по умолчанию небезопасен.
ПРЕДУПРЕЖДЕНИЕ
Если вы используете ссылки в качестве ключей в ваших таблицах хэшей, вы, вероятно, будете разочарованы при получении данных. Действительно, Perl строит ссылки, используемые в качестве ключей таблицы хэшей. Если вы позже захотите получить доступ к элементам с помощью другой строковой записи ссылок (т.е. используя ту же ссылку, которая использовалась для ключа изначально, чтобы записать значение в таблицу хэшей), она будет работать, потому что обе ссылки строятся в одну и ту же строку.
Однако она не будет работать при последовательности операций store и retrieve, потому что адреса в полученных объектах, которые являются частью строковых представлений ссылок, вероятно, будут отличаться от исходных адресов. Топология вашей структуры сохраняется, но не скрытые семантические значения, подобные этим.
На платформах, где это имеет значение, обязательно вызывайте binmode() для дескрипторов, которые вы передаёте функциям Storable.
Хранение канонических данных, содержащих большие хэши, может быть значительно медленнее, чем хранение тех же данных обычно, так как временные массивы для хранения ключей каждого хэша должны быть выделены, заполнены, отсортированы и освобождены. Некоторые тесты показали, что скорость хранения уменьшилась вдвое — точное значение наказания зависит от сложности ваших данных. Замедления при получении данных нет.
РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ
Storable теперь экспериментально поддерживает хранение регулярных выражений, но существуют значительные ограничения:
-
Требуется perl 5.8 или более поздняя версия.
-
регулярные выражения с блоками кода, например
/(?{ ... })/или/(??{ ... })/будут вызывать исключение при размораживании. -
синтаксис и флаги регулярных выражений менялись на протяжении истории perl, поэтому регулярное выражение, замороженное в одной версии perl, может не разморозиться или вести себя по-другому в другой версии perl.
-
в зависимости от версии perl, поведение регулярных выражений может меняться в зависимости от контекста, но более поздние версии perl будут включать это поведение в regexp.
Storable сгенерирует исключение, если замороженное регулярное выражение невозможно разморозить.
ОШИБКИ
Вы не можете сохранить GLOB, FORMLINE и т.д.... Если вы можете определить семантику для этих операций, не стесняйтесь улучшать Storable, чтобы он мог с ними работать.
Функции хранения croak , если они сталкиваются с такими ссылками, если вы не зададите $Storable::forgive_me какое-то TRUE значение. В этом случае сообщение об ошибке преобразуется в предупреждение, и вместо этого сохраняется какое-то бессмысленное строковое значение.
Установка $Storable::canonical может не привести к замороженным строкам, которые сравниваются как равные из-за возможного преобразования чисел в строки. Если существует строковая версия скаляра, сохраняется именно она; поэтому, если вы используете числа как строки между двумя операциями заморозки одних и тех же структур данных, вы получите разные результаты.
При хранении чисел с плавающей точкой в сетевом порядке их значение хранится как текст. Однако не следует ожидать, что нечисловые значения с плавающей точкой, такие как бесконечность и «не число», успешно пройдут через пару nstore()/retrieve().
Так как Storable не знает и не заботится о наборах символов (хотя он знает, что символы могут быть шире восьми бит), любые различия в интерпретации кодов символов между хостом и целевой системой — ваша проблема. В частности, если хост и целевая система используют разные кодовые точки для представления символов, используемых в текстовом представлении чисел с плавающей точкой, вы не сможете обмениваться данными с плавающей точкой, даже с помощью nstore().
Storable::drop_utf8 — это грубый инструмент. Нет возможности вернуть все строки как последовательности utf8 или попытаться преобразовать данные utf8 обратно в 8-битные и croak() в случае неудачи преобразования.
До Storable 2.01 не проводилось различий между знаковыми и беззнаковыми целыми числами при сохранении. По умолчанию Storable предпочитает сохранять строковое представление скаляра (если оно есть), поэтому это вызывало бы проблемы только при сохранении больших беззнаковых целых чисел, которые никогда не были преобразованы в строку или число с плавающей точкой. Другими словами, это касается значений, которые были получены с помощью целочисленных операций, таких как логические операции, и затем не использовались в строковом или арифметическом контексте перед сохранением.
64-битные данные в perl 5.6.0 и 5.6.1
Этот раздел относится только к вам, если у вас есть существующие данные, записанные Storable 2.02 или более ранней версией на perl 5.6.0 или 5.6.1 под Unix или Linux, настроенные с поддержкой 64-битных целых чисел (не по умолчанию). Если вы использовали предварительно скомпилированный perl, а не запускали Configure для сборки своего perl из исходного кода, это почти наверняка на вас не повлияет, и вы можете прекратить чтение (если вас не интересует). Если вы используете perl на Windows, это вас не коснется.
Storable записывает заголовок файла, который содержит размеры различных типов языка C для компилятора C, который создал Storable (при записи не в сетевом порядке), и откажется загрузить файлы, записанные Storable не на той же (или совместимой) архитектуре. Эта проверка и проверка порядка байтов машины необходимы, потому что размер различных полей в файле определяется размерами типов языка C, поэтому файлы, записанные на разных архитектурах, несовместимы. Это делается для повышения скорости. (При записи в сетевом порядке все поля записываются в виде стандартной длины, что позволяет обеспечить полную взаимозаменяемость, но медленнее чтение и запись)
Perl 5.6.x ввел возможность необязательно настроить интерпретатор perl для использования типа C long long для хранения 64-битных целых чисел в 32-битных системах. Однако из-за того, как система конфигурации Perl генерировала файлы конфигурации C на платформах, не являющихся Windows, и как Storable генерировал свой заголовок, ничего в заголовке файла Storable не отражало, использовал ли perl при записи 32- или 64-битные целые числа, несмотря на то, что Storable хранил некоторые данные в файле по-разному. Следовательно, Storable, работающий в perl с 64-битными целыми числами, будет читать заголовок из файла, записанного 32-битным perl, не осознает, что данные фактически находятся в слегка несовместимом формате, и затем может серьёзно выйти из строя (возможно, аварийно завершится), если обнаружит сохранённое целое число. Это ошибка проектирования.
Теперь Storable изменён так, чтобы записывать и читать заголовок файла с информацией о размере целых чисел. Невозможно определить, был ли старый файл, который читается, записан с 32- или 64-битными целыми числами (у них одинаковый заголовок), поэтому невозможно автоматически переключиться на правильный режим обратной совместимости. Следовательно, Storable по умолчанию использует новое, правильное поведение.
Это означает, что если у вас есть данные, записанные Storable 1.x, работающим на perl 5.6.0 или 5.6.1, настроенным с 64-битными целыми числами под Unix или Linux, то по умолчанию этот Storable откажется их читать, выдав ошибку Порядок байтов несовместим. Если у вас есть такие данные, вы должны установить $Storable::interwork_56_64bit в истинное значение, чтобы этот Storable читал и записывал файлы со старым заголовком. Вам также следует перенести свои данные или любой более старый perl, с которым вы общаетесь, на текущую версию Storable.
Если у вас нет данных, записанных с указанной выше конфигурацией perl, то ничего не делайте и не должны делать. Не устанавливайте флаг — Storable с идентичной конфигурацией perl откажется от загрузки, но Storable с другой конфигурацией perl загрузит их, считая их правильными для него, а затем, возможно, выйдет из строя или аварийно завершит чтение.
АВТОРЫ
Благодарим (в хронологическом порядке):
Jarkko Hietaniemi <jhi@iki.fi>
Ulrich Pfeifer <pfeifer@charly.informatik.uni-dortmund.de>
Benjamin A. Holzman <bholzman@earthlink.net>
Andrew Ford <A.Ford@ford-mason.co.uk>
Gisle Aas <gisle@aas.no>
Jeff Gresham <gresham_jeffrey@jpmorgan.com>
Murray Nesbitt <murray@activestate.com>
Marc Lehmann <pcg@opengroup.org>
Justin Banks <justinb@wamnet.com>
Jarkko Hietaniemi <jhi@iki.fi> (AGAIN, as perl 5.7.0 Pumpkin!)
Salvador Ortiz Garcia <sog@msg.com.mx>
Dominic Dunlop <domo@computer.org>
Erik Haugan <erik@solbors.no>
Benjamin A. Holzman <ben.holzman@grantstreet.com>
Reini Urban <rurban@cpan.org>
Todd Rinaldo <toddr@cpanel.net>
Aaron Crane <arc@cpan.org> за их сообщения об ошибках, предложения и вклад.
Benjamin Holzman внес вклад в поддержку связанных переменных, Andrew Ford — в канонический порядок для хешей, а Gisle Aas исправил несколько моих непониманий в отношении внутренних механизмов perl и оптимизировал вывод «меток» в потоках вывода, просто подсчитывая объекты вместо их маркировки (что привело к двоичной несовместимости для изображения Storable, начиная с версии 0.6 — более старые изображения, конечно, по-прежнему правильно понимаются). Murray Nesbitt сделал Storable потокобезопасным. Marc Lehmann добавил поддержку перегрузки и ссылок на связанные элементы. Benjamin Holzman добавил улучшение производительности для перегруженных классов; спасибо Grant Street Group за финансирование. Reini Urban взял на себя обслуживание от p5p и добавил исправления безопасности и поддержку больших объектов.
АВТОР
Storable был написан Raphael Manfredi <Raphael_Manfredi@pobox.com> Техническое обслуживание теперь выполняется cperl http://perl11.org/cperl
Пожалуйста, пишите нам с проблемами, исправлениями ошибок, замечаниями и жалобами, хотя если у вас есть комплименты, вы должны отправить их Raphael. Пожалуйста, не отправляйте Raphael проблемы, так как он больше не работает над Storable, и ваше сообщение задержится, пока он не перенаправит его нам.
СМОТРИТЕ ТАКЖЕ
© 1993–2020 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.30.3/Storable