I don't normally manipulate $/ so wanted to give your report some
proper study before determining the correct course of action -
unfortunately nearly 4 months snuck in between that thought and my
first serious attempt to get to the bottom of what you reported.
When I tried to reproduce the error you were reporting, I could not
actually do so under normal operations. No matter how many newlines
one put at the end of a serialized data structure, it would
deserialize just fine.
What I was able to determine was that if you undefine $/ in the
global context I could reproduce what you were describing. Looking
at perldoc perlvar, it has this to say on the subject:
[snip]
You should be very careful when modifying the default values
of most
special variables described in this document. In most cases
you want to
localize these variables before changing them, since if you
don't, the
change may affect other modules which rely on the default
values of the
special variables that you have changed. This is one of the
correct
ways to read the whole file at once:
open my $fh, "foo" or die $!;
local $/; # enable localized slurp mode
my $content = <$fh>;
close $fh;
But the following code is quite bad:
open my $fh, "foo" or die $!;
undef $/; # enable slurp mode
my $content = <$fh>;
close $fh;
since some other module, may want to read data from some file
in the
default "line mode", so if the code we have just presented
has been
executed, the global value of $/ is now changed for any other
code run-
ning inside the same Perl interpreter.
Usually when a variable is localized you want to make sure
that this
change affects the shortest scope possible. So unless you are
already
inside some short "{}" block, you should create one yourself.
For exam-
ple:
my $content = '';
open my $fh, "foo" or die $!;
{
local $/;
$content = <$fh>;
}
close $fh;
[/snip]
With this said, can you reproduce this problem with the following
test code:
[snip]
#!/usr/bin/perl
use warnings;
use strict;
use Data::Serializer;
use Data::Dumper;
my $d = Data::Serializer->new();
{
local $/;
my $ref = {a => 'b'};
my $serialized = $d->serialize($ref);
#$d->store($ref,'store.txt');
open(OUT, '>', 'store.txt') || die "Couldn't write to
store.txt: $!\n";
print OUT "$serialized\n\n\n";
close(OUT);
}
#File method
my $thaw = $d->retrieve('store.txt');
print Dumper $thaw;
#Filehandle method
open(IN, '<', 'store.txt');
my $fh_thaw = $d->retrieve(\*IN);
close(IN);
print Dumper $fh_thaw;
[/snip]
As you can see from the above, that is storing a serialized value
followed with three newlines, with a localized $/ undefined. As long
as $/ remains correctly defined on the reading side these functions
should operate correctly.
My main hesitation with altering this behavior is that I like the
functionality of $/ as it varies per OS, and by relying on it being
correctly set it keeps Data::Serializer from having to understand or
care about what that value happens to be. That said, I am open to
being convinced otherwise and making Data::Serializer play nicer with
those who mess with their $/ in the global namespace.
--
Neil
On Dec 12, 2006, at 8:50 AM, Jamie Lentin via RT wrote:
Show quoted text>
> Tue Dec 12 10:50:49 2006: Request 23901 was acted upon.
> Transaction: Ticket created by lentinj
> Queue: Data-Serializer
> Subject: Data::Serializer::Retrieve doesn't slurp files
> Broken in: 0.32, 0.36
> Severity: Normal
> Owner: Nobody
> Requestors: jamie.lentin@bbc.co.uk
> Status: new
> Ticket <URL:
http://rt.cpan.org/Ticket/Display.html?id=23901 >
>
>
> If you try to use retrieve to read a file that contains a newline, the
> deserialization won't work. When retrieve() reads a file into $input,
> it will stop at any \n in the file since $/ is still defined.
>
> A "local $/" at the beginning of the function should sort it. Or
> alternatively using File::Slurp or something.
>
> Cheers for all your work!