10.3.2 Using a File to Store Serialized Data Structures with Data::Serialize.pm

10.3.2  Using a File to Store Serialized Data Structures with Data::Serialize.pm

   The program in Section 10.3.1 serializes four data structures into strings and deserializes them again, obtaining the original contents. The program illustrates that serialization and deserialization are useful tools whether we are dealing with simple or complex data structures. In this Section, we rewrite the program of Section 10.3.1. In the current program, we write each of the serialized data structures to a file data.txt. Each serialized string is printed to the file as a line by itself. In the second part of the program, the file data.txt is opened for reading. Each of the serialized or frozen data structures is deserialized or thawed, and the output written to the standard output or screen. The program follows.

 Program 10.9

#!/usr/bin/perl
#serializeFile.pl

use Data::Serializer;
use strict;

#create a new serializer
my $dumper = Data::Serializer -> new ();

#serialize a scalar
my $friend = "Justin O'Malley";
my $serializedFriend = $dumper->serialize (\$friend);

#write the serialized object into file data.txt; follow by "\n";
open OUT,  ">data.txt";
print OUT $serializedFriend, "\n";

#serialize a list or array; print into data.txt, follow by "\n"
my @friends = ("Justin O'Malley", "Christopher Paul", "Shane Jahnke", 
               "Seth Gross", "Seth Musselman", "Greg Eisenbeis");
my $serializedFriends = $dumper->serialize (\@friends);
print OUT $serializedFriends, "\n";

#serialize a hash, write to data.txt, follow by |'n";
my %hobbies = ("Chris Paul" => "Skiing/Working out", 
                     "Justin O'Malley" => "Singing/Acting", ,
                     "Shane Jahnke" => "Soccer",
                     "Seth Gross" => "Soccer/School",
                     "Seth Musselman" => "Sailing",
                     "Greg Eisenbeis" => "Girls");
my $serializedHobbies = $dumper->serialize(\%hobbies);
print OUT $serializedHobbies, "\n";

#serialize an array of arrays; write into OUT, follow by "\n"
my $friendsStats = [ ['Chris Paul', 'Colorado Springs', 23, 76, 180],
               ['Shane Jahnke', 'Colorado Springs', 19, 73, 150],
               ['Seth Gross', 'Colorado Springs', 20, 70, 160],
               ['Seth Musselman', 'Colorado Springs', 22, 74, 170],
               ['Greg Eisenbeis', 'Colorado Springs', 22, 76, 165]
               ];
my $serializedStats = $dumper->serialize ($friendsStats);
print OUT $serializedStats, "\n";

#Close the file handle; reading the serialized data in the same
#program will not work if not closed; at the end of a program
#a file handle is closed automatically. 
close OUT;

#######################
#READ BACK FROM THE FILE
open IN, "data.txt";

#Read the serialized scalar back, remove "\n" from end, deserialize it
my $serializedFriend = ;
chomp ($serializedFriend);
my $friendAgain = $dumper -> deserialize ($serializedFriend);
print "friendAgain = $$friendAgain \n";

#Read the serialized array back, remove "\n", deserialize it
$serializedFriends = ;
chomp ($serializedFriends);
my $friendsAgain = $dumper->deserialize ($serializedFriends);
print "friendsAgain = ", join ("\n\t", @$friendsAgain), "\n";

#Read the serialized hash back, remove "\n", deserialize it
$serializedHobbies = ;
chomp ($serializedHobbies);
my $hobbiesAgain = $dumper-> deserialize ($serializedHobbies);
my $person;
print "\nFriends and their hobbies:\n";
foreach $person (keys %$hobbiesAgain){
    print $person, "\t\t", $$hobbiesAgain{$person}, "\n";
}

#Read the serialized array of arrays back, remove "\n", deserialize it
$serializedStats = ;
chomp ($serializedStats);
my $statsAgain = $dumper->deserialize ($serializedStats);
my $i;
print "\nFriends and their stats:\n";
for ($i=0; $i <= 4; $i++){
    printf "%-15s %-15s  %3d  %3d  %3d\n",
      $statsAgain -> [$i] -> [0], $statsAgain -> [$i] -> [1], 
      $statsAgain -> [$i] -> [2], $statsAgain -> [$i] -> [3], 
      $statsAgain -> [$i] -> [4];
}

close IN;

The program starts by creating a new Data::Serializer object called $dumper. $dumper is used for all serialization and deserialization. First, the scalar $friend is serialized into $serializedFriend which is written into the file data.txt followed by a newline character.

 

open OUT,  ">data.txt";

print OUT $serializedFriend, "\n";

 

Next, the list @friends is assigned a value, serialized, and the serialized string written out to the file data.txt, followed by a newline character.

 

print OUT $serializedFriends, "\n";

 

Similarly, the hash %hobbies, and the array of arrays referenced by $friendsStats, are serialized and written out to the same file data.txt. Finally, an anonymous array of arrays is serialized and stored to the file. The OUT filehandle is closed so that everything is written out to the file correctly.

The second part of the program opens the same file data.txt for reading, reads the four lines in the file one by one, and deserializes the strings to obtain the original data structures. The contents of the original data structures are printed out to the standard output or screen. For example, the following lines of code read the fourth string from the file, and obtain the original contents of the array of arrays.

 

$serializedStats = <IN>;

chomp ($serializedStats);

my $statsAgain = $dumper->deserialize ($serializedStats);

 

Note that when the program writes into the file in the first half, the serialized string is followed by a \n as it is printed into the file. Therefore, at the unrolling end, after the line containing the serialized string has been read, it is chomped to remove the \n inserted at the end.

When several serialized strings are stored in the same file, they must be read back in the exact same order. In addition, if any additional characters, such as \n are inserted into the same file, they must be read back in the exact same order, in the exact same place. If the order is not followed exactly, the deserialization process complains about extraneous or non-understood characters and fails.

The contents of the file data.txt after the program has been run are given below for the perusal of the curious-minded. The strings that are produced by serialization are a sequence of hexa-decimal digits. Some of the lines are long and hence are broken into pieces. Each data structure starts with the string ^Data::Dumper|||hex|^.

 

 

^Data::Dumper|||hex|^5c274a757374696e204f5c274d616c6c657927

^Data::Dumper|||hex|^5b274a757374696e204f5c274d616c6c6579272c274368726973746f7068657220

5061756c272c275368616e65204a61686e6b65272c27536574682047726f7373272c2753657468204d75737

3656c6d616e272c274772656720456973656e62656973275d

^Data::Dumper|||hex|^7b274772656720456973656e6265697327203d3e20274769726c73272c274a7573

74696e204f5c274d616c6c657927203d3e202753696e67696e672f416374696e67272c2753657468204d757

373656c6d616e27203d3e20275361696c696e67272c27536574682047726f737327203d3e2027536f636365

722f5363686f6f6c272c275368616e65204a61686e6b6527203d3e2027536f63636572272c2743687269732

05061756c27203d3e2027536b69696e672f576f726b696e67206f7574277d

^Data::Dumper|||hex|^5b5b274368726973205061756c272c27436f6c6f7261646f20537072696e677327

2c32332c37362c3138305d2c5b275368616e6b65204a61686e6b65272c27436f6c6f7261646f20537072696

e6773272c31392c37332c3135305d2c5b27536574682047726f7373272c27436f6c6f7261646f2053707269

6e6773272c32302c37302c3136305d2c5b2753657468204d757373656c6d616e272c27436f6c6f7261646f2

0537072696e6773272c32322c37342c3137305d2c5b274772656720456973656e62656973272c27436f6c6f

7261646f20537072696e6773272c32322c37362c3136355d5d