rendler has asked for the wisdom of the Perl Monks concerning the following question:

Okay my problem is when trying to use a dbm file from my system on another, which may be a completely different operating system, the file will not work because of the different version libraries installed or whatnot, so I came up with the 2 scripts below.
#!/usr/bin/perl -w use strict; use DB_File; die "usage: dview <file.db> <outputfile>\n" unless (@ARGV == 2); my($db_file, $out_file) = @ARGV; die "Error: $!\n" unless -e $db_file; die "Output file exists\n" if -e $out_file; open OUT_FILE, ">$out_file" or die "Couldn't open $out_file: $!\n"; dbmopen my %DB, "$db_file", 0666 or die "Couldn't open DB: $!\n"; for (sort keys %DB) { print OUT_FILE "key: \"$_\" = \"$DB{$_}\" END\n"; } dbmclose %DB or warn "Couldn't close $db_file: $!\n"; close OUT_FILE or warn "Couldn't close $out_file: $!\n";
That one would dump the contents of the dbm file's hash values into a plain text file and with that plain text file I would create another dbm file with this other script
#!/usr/bin/perl -w use strict; use DB_File; die "usage: dbcreate-dump <file> <out.db>\n" unless (@ARGV == 2); my($in_file, $out_db) = @ARGV; die "Error: $!\n" unless -e $in_file; die "Output DB exists\n" if -e $out_db; local $/; open IN_FILE, "< $in_file" or die "Couldn't open $in_file: $!\n"; my $file_contents = <IN_FILE>; close IN_FILE or warn "Couldn't close $in_file: $!\n"; dbmopen my %DB, "$out_db", 0666 or die "Couldn't open DB: $!\n"; while($file_contents =~ /key: \"(.*)\" = \"(.*)\" END/g) { $DB{$1} = $2; } dbmclose %DB or warn "Couldn't close $out_db: $!\n";
But all that seems a little over complicated I thought when I remembered Data::Dumper and maybe using it dump the values into a plain text file and eval that or something. But the something is where I'm stuck I have no idea how to achive this using Data::Dumper, so far I've tried
#!/usr/bin/perl -w use strict; use DB_File; use Data::Dumper; dbmopen my %NEWS_DB, "news.db", 0666 or die "Couldn't open news.db: $! +\n"; my $news_db = \%NEWS_DB; my $data = Dumper $news_db; dbmopen my %NEW_DB, "new.db", 0666 or die "Couldn't open new.db: $!\n" +; %NEW_DB = eval(Dumper($data));
Of course that doesn't work and the Data::Dumper man page just confuses me even more :( so any help would be greatly appreciated.

Replies are listed 'Best First'.
Re: DBM files between systems
by grep (Monsignor) on Feb 23, 2002 at 06:58 UTC
    You'll most likely be better off using Freeze::Thaw.

    from the module docs:
    Converts data to/from stringified form, appropriate for saving-to/reading-from permanent storage.

    You could also try to use Text::CSV_XS for csv files.

    grep
    grep> rm -f /bin/laden
Re: DBM files between systems
by Speedy (Monk) on Feb 23, 2002 at 20:17 UTC
    Christiansen & Torkington in the Perl Cookbook, Chapter 14, recipe 3 - "Converting between DBM files", show something similar to your code.

    The relevant portion of that code for your problem is:

    # open the files tie(%db_in, 'DB_File', $infile) or die "Can't tie $infile: $!"; tie(%db_out, 'GDBM_File', $outfile, GDBM_WRCREAT, 0666) or die "Can't tie $outfile: $!"; # copy (don't use %db_out = %db_in because it's slow on big databases) while (my($k, $v) = each %db_in) { $db_out{$k} = $v; }
    I think you may be overcomplicating the text-file creation part. Why not just modify the Cookbook code above a bit with something like this snippet:
    # open the files tie(%db_in, 'DB_File', $infile) or die "Can't tie $infile: $!"; open TEXT_OUT, ">$outfile" or die "Can't open $outfile: $!"; while (my($key, $value) = each %db_in) { print TEXT_OUT "$key\n$value\n"; }
    This way you need not slurp the whole file in (may not be scalable if the original file is large), and after moving the text file to the new system you need only reverse the process, making each odd row the key and the next row the new DBM value of the new file. Even if $value happened to be undef, that state is still preserved.

    I only ask for information. -- Charles Dickens David Copperfield