storable.html
来自「perl教程」· HTML 代码 · 共 740 行 · 第 1/3 页
HTML
740 行
B, and if there is a serializing hook in A that says freeze(B), then when
deserializing, we'll get [A', C'] where A' refers to B', but C' refers to D,
a deep clone of B'. The topology was not preserved.</p>
</li>
</ul>
<p>That's why <code>STORABLE_freeze</code> lets you provide a list of references
to serialize. The engine guarantees that those will be serialized in the
same context as the other objects, and therefore that shared objects will
stay shared.</p>
<p>In the above [A, C] example, the <code>STORABLE_freeze</code> hook could return:</p>
<pre>
<span class="operator">(</span><span class="string">"something"</span><span class="operator">,</span> <span class="variable">$self</span><span class="operator">-></span><span class="operator">{</span><span class="string">B</span><span class="operator">}</span><span class="operator">)</span>
</pre>
<p>and the B part would be serialized by the engine. In <code>STORABLE_thaw</code>, you
would get back the reference to the B' object, deserialized for you.</p>
<p>Therefore, recursion should normally be avoided, but is nonetheless supported.</p>
<p>
</p>
<h2><a name="deep_cloning">Deep Cloning</a></h2>
<p>There is a Clone module available on CPAN which implements deep cloning
natively, i.e. without freezing to memory and thawing the result. It is
aimed to replace Storable's <code>dclone()</code> some day. However, it does not currently
support Storable hooks to redefine the way deep cloning is performed.</p>
<p>
</p>
<hr />
<h1><a name="storable_magic">Storable magic</a></h1>
<p>Yes, there's a lot of that :-) But more precisely, in UNIX systems
there's a utility called <code>file</code>, which recognizes data files based on
their contents (usually their first few bytes). For this to work,
a certain file called <em>magic</em> needs to taught about the <em>signature</em>
of the data. Where that configuration file lives depends on the UNIX
flavour; often it's something like <em>/usr/share/misc/magic</em> or
<em>/etc/magic</em>. Your system administrator needs to do the updating of
the <em>magic</em> file. The necessary signature information is output to
STDOUT by invoking Storable::show_file_magic(). Note that the GNU
implementation of the <code>file</code> utility, version 3.38 or later,
is expected to contain support for recognising Storable files
out-of-the-box, in addition to other kinds of Perl files.</p>
<p>
</p>
<hr />
<h1><a name="examples">EXAMPLES</a></h1>
<p>Here are some code samples showing a possible usage of Storable:</p>
<pre>
<span class="keyword">use</span> <span class="variable">Storable</span> <span class="string">qw(store retrieve freeze thaw dclone)</span><span class="operator">;</span>
</pre>
<pre>
<span class="variable">%color</span> <span class="operator">=</span> <span class="operator">(</span><span class="string">'Blue'</span> <span class="operator">=></span> <span class="number">0</span><span class="operator">.</span><span class="number">1</span><span class="operator">,</span> <span class="string">'Red'</span> <span class="operator">=></span> <span class="number">0</span><span class="operator">.</span><span class="number">8</span><span class="operator">,</span> <span class="string">'Black'</span> <span class="operator">=></span> <span class="number">0</span><span class="operator">,</span> <span class="string">'White'</span> <span class="operator">=></span> <span class="number">1</span><span class="operator">);</span>
</pre>
<pre>
<span class="variable">store</span><span class="operator">(\</span><span class="variable">%color</span><span class="operator">,</span> <span class="string">'mycolors'</span><span class="operator">)</span> <span class="keyword">or</span> <span class="keyword">die</span> <span class="string">"Can't store %a in mycolors!\n"</span><span class="operator">;</span>
</pre>
<pre>
<span class="variable">$colref</span> <span class="operator">=</span> <span class="variable">retrieve</span><span class="operator">(</span><span class="string">'mycolors'</span><span class="operator">);</span>
<span class="keyword">die</span> <span class="string">"Unable to retrieve from mycolors!\n"</span> <span class="keyword">unless</span> <span class="keyword">defined</span> <span class="variable">$colref</span><span class="operator">;</span>
<span class="keyword">printf</span> <span class="string">"Blue is still %lf\n"</span><span class="operator">,</span> <span class="variable">$colref</span><span class="operator">-></span><span class="operator">{</span><span class="string">'Blue'</span><span class="operator">}</span><span class="operator">;</span>
</pre>
<pre>
<span class="variable">$colref2</span> <span class="operator">=</span> <span class="variable">dclone</span><span class="operator">(\</span><span class="variable">%color</span><span class="operator">);</span>
</pre>
<pre>
<span class="variable">$str</span> <span class="operator">=</span> <span class="variable">freeze</span><span class="operator">(\</span><span class="variable">%color</span><span class="operator">);</span>
<span class="keyword">printf</span> <span class="string">"Serialization of %%color is %d bytes long.\n"</span><span class="operator">,</span> <span class="keyword">length</span><span class="operator">(</span><span class="variable">$str</span><span class="operator">);</span>
<span class="variable">$colref3</span> <span class="operator">=</span> <span class="variable">thaw</span><span class="operator">(</span><span class="variable">$str</span><span class="operator">);</span>
</pre>
<p>which prints (on my machine):</p>
<pre>
Blue is still 0.100000
Serialization of %color is 102 bytes long.</pre>
<p>Serialization of CODE references and deserialization in a safe
compartment:</p>
<pre>
<span class="keyword">use</span> <span class="variable">Storable</span> <span class="string">qw(freeze thaw)</span><span class="operator">;</span>
<span class="keyword">use</span> <span class="variable">Safe</span><span class="operator">;</span>
<span class="keyword">use</span> <span class="variable">strict</span><span class="operator">;</span>
<span class="keyword">my</span> <span class="variable">$safe</span> <span class="operator">=</span> <span class="variable">new</span> <span class="variable">Safe</span><span class="operator">;</span>
<span class="comment"># because of opcodes used in "use strict":</span>
<span class="variable">$safe</span><span class="operator">-></span><span class="variable">permit</span><span class="operator">(</span><span class="string">qw(:default require)</span><span class="operator">);</span>
<span class="keyword">local</span> <span class="variable">$Storable::Deparse</span> <span class="operator">=</span> <span class="number">1</span><span class="operator">;</span>
<span class="keyword">local</span> <span class="variable">$Storable::Eval</span> <span class="operator">=</span> <span class="keyword">sub</span><span class="variable"> </span><span class="operator">{</span> <span class="variable">$safe</span><span class="operator">-></span><span class="variable">reval</span><span class="operator">(</span><span class="variable">$_</span><span class="operator">[</span><span class="number">0</span><span class="operator">]</span><span class="operator">)</span> <span class="operator">};</span>
<span class="keyword">my</span> <span class="variable">$serialized</span> <span class="operator">=</span> <span class="variable">freeze</span><span class="operator">(</span><span class="keyword">sub</span><span class="variable"> </span><span class="operator">{</span> <span class="number">42</span> <span class="operator">});</span>
<span class="keyword">my</span> <span class="variable">$code</span> <span class="operator">=</span> <span class="variable">thaw</span><span class="operator">(</span><span class="variable">$serialized</span><span class="operator">);</span>
<span class="variable">$code</span><span class="operator">->()</span> <span class="operator">==</span> <span class="number">42</span><span class="operator">;</span>
</pre>
<p>
</p>
<hr />
<h1><a name="warning">WARNING</a></h1>
<p>If you're using references as keys within your hash tables, you're bound
to be disappointed when retrieving your data. Indeed, Perl stringifies
references used as hash table keys. If you later wish to access the
items via another reference stringification (i.e. using the same
reference that was used for the key originally to record the value into
the hash table), it will work because both references stringify to the
same string.</p>
<p>It won't work across a sequence of <code>store</code> and <code>retrieve</code> operations,
however, because the addresses in the retrieved objects, which are
part of the stringified references, will probably differ from the
original addresses. The topology of your structure is preserved,
but not hidden semantics like those.</p>
<p>On platforms where it matters, be sure to call <a href="../lib/Pod/perlfunc.html#item_binmode"><code>binmode()</code></a> on the
descriptors that you pass to Storable functions.</p>
<p>Storing data canonically that contains large hashes can be
significantly slower than storing the same data normally, as
temporary arrays to hold the keys for each hash have to be allocated,
populated, sorted and freed. Some tests have shown a halving of the
speed of storing -- the exact penalty will depend on the complexity of
your data. There is no slowdown on retrieval.</p>
<p>
</p>
<hr />
<h1><a name="bugs">BUGS</a></h1>
<p>You can't store GLOB, FORMLINE, etc.... If you can define semantics
for those operations, feel free to enhance Storable so that it can
deal with them.</p>
<p>The store functions will <code>croak</code> if they run into such references
unless you set <code>$Storable::forgive_me</code> to some <code>TRUE</code> value. In that
case, the fatal message is turned in a warning and some
meaningless string is stored instead.</p>
<p>Setting <code>$Storable::canonical</code> may not yield frozen strings that
compare equal due to possible stringification of numbers. When the
string version of a scalar exists, it is the form stored; therefore,
if you happen to use your numbers as strings between two freezing
operations on the same data structures, you will get different
results.</p>
<p>When storing doubles in network order, their value is stored as text.
However, you should also not expect non-numeric floating-point values
such as infinity and "not a number" to pass successfully through a
<code>nstore()/retrieve()</code> pair.</p>
<p>As Storable neither knows nor cares about character sets (although it
does know that characters may be more than eight bits wide), any difference
in the interpretation of character codes between a host and a target
system is your problem. In particular, if host and target use different
code points to represent the characters used in the text representation
of floating-point numbers, you will not be able be able to exchange
floating-point data, even with nstore().</p>
<p><code>Storable::drop_utf8</code> is a blunt tool. There is no facility either to
return <strong>all</strong> strings as utf8 sequences, or to attempt to convert utf8
data back to 8 bit and <code>croak()</code> if the conversion fails.</p>
<p>Prior to Storable 2.01, no distinction was made between signed and
unsigned integers on storing. By default Storable prefers to store a
scalars string representation (if it has one) so this would only cause
problems when storing large unsigned integers that had never been coverted
to string or floating point. In other words values that had been generated
by integer operations such as logic ops and then not used in any string or
arithmetic context before storing.</p>
<p>
</p>
<h2><a name="64_bit_data_in_perl_5_6_0_and_5_6_1">64 bit data in perl 5.6.0 and 5.6.1</a></h2>
<p>This section only applies to you if you have existing data written out
by Storable 2.02 or earlier on perl 5.6.0 or 5.6.1 on Unix or Linux which
has been configured with 64 bit integer support (not the default)
If you got a precompiled perl, rather than running Configure to build
your own perl from source, then it almost certainly does not affect you,
and you can stop reading now (unless you're curious). If you're using perl
on Windows it does not affect you.</p>
<p>Storable writes a file header which contains the sizes of various C
language types for the C compiler that built Storable (when not writing in
network order), and will refuse to load files written by a Storable not
on the same (or compatible) architecture. This check and a check on
machine byteorder is needed because the size of various fields in the file
are given by the sizes of the C language types, and so files written on
different architectures are incompatible. This is done for increased speed.
(When writing in network order, all fields are written out as standard
lengths, which allows full interworking, but takes longer to read and write)</p>
<p>Perl 5.6.x introduced the ability to optional configure the perl interpreter
to use C's <code>long long</code> type to allow scalars to store 64 bit integers on 32
bit systems. However, due to the way the Perl configuration system
generated the C configuration files on non-Windows platforms, and the way
Storable generates its header, nothing in the Storable file header reflected
whether the perl writing was using 32 or 64 bit integers, despite the fact
that Storable was storing some data differently in the file. Hence Storable
running on perl with 64 bit integers will read the header from a file
written by a 32 bit perl, not realise that the data is actually in a subtly
incompatible format, and then go horribly wrong (possibly crashing) if it
encountered a stored integer. This is a design failure.</p>
<p>Storable has now been changed to write out and read in a file header with
information about the size of integers. It's impossible to detect whether
an old file being read in was written with 32 or 64 bit integers (they have
the same header) so it's impossible to automatically switch to a correct
backwards compatibility mode. Hence this Storable defaults to the new,
correct behaviour.</p>
<p>What this means is that if you have data written by Storable 1.x running
on perl 5.6.0 or 5.6.1 configured with 64 bit integers on Unix or Linux
then by default this Storable will refuse to read it, giving the error
<em>Byte order is not compatible</em>. If you have such data then you you
should set <code>$Storable::interwork_56_64bit</code> to a true value to make this
Storable read and write files with the old header. You should also
migrate your data, or any older perl you are communicating with, to this
current version of Storable.</p>
<p>If you don't have data written with specific configuration of perl described
above, then you do not and should not do anything. Don't set the flag -
not only will Storable on an identically configured perl refuse to load them,
but Storable a differently configured perl will load them believing them
to be correct for it, and then may well fail or crash part way through
reading them.</p>
<p>
</p>
<hr />
<h1><a name="credits">CREDITS</a></h1>
<p>Thank you to (in chronological order):</p>
<pre>
Jarkko Hietaniemi <jhi@iki.fi>
Ulrich Pfeifer <pfeifer@charly.informatik.uni-dortmund.de>
Benjamin A. Holzman <bah@ecnvantage.com>
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></pre>
<p>for their bug reports, suggestions and contributions.</p>
<p>Benjamin Holzman contributed the tied variable support, Andrew Ford
contributed the canonical order for hashes, and Gisle Aas fixed
a few misunderstandings of mine regarding the perl internals,
and optimized the emission of "tags" in the output streams by
simply counting the objects instead of tagging them (leading to
a binary incompatibility for the Storable image starting at version
0.6--older images are, of course, still properly understood).
Murray Nesbitt made Storable thread-safe. Marc Lehmann added overloading
and references to tied items support.</p>
<p>
</p>
<hr />
<h1><a name="author">AUTHOR</a></h1>
<p>Storable was written by Raphael Manfredi <em><<a href="mailto:Raphael_Manfredi@pobox.com">Raphael_Manfredi@pobox.com</a>></em>
Maintenance is now done by the perl5-porters <em><<a href="mailto:perl5-porters@perl.org">perl5-porters@perl.org</a>></em></p>
<p>Please e-mail us with problems, bug fixes, comments and complaints,
although if you have complements you should send them to Raphael.
Please don't e-mail Raphael with problems, as he no longer works on
Storable, and your message will be delayed while he forwards it to us.</p>
<p>
</p>
<hr />
<h1><a name="see_also">SEE ALSO</a></h1>
<p><em>Clone</em>.</p>
</body>
</html>
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?