Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

File as has can it be done? 2

Status
Not open for further replies.

alexv1

Programmer
Joined
Dec 9, 2006
Messages
4
Location
US
Ok so I have been searching for hours because I thought this would be easy but I can't seem to find anything so any help would be much appreciated. Here is what I have and what I am trying to do with it.

I have a file that is in perfect hash format. I want to be able to just read the file in as a hash. Here is a sample file of what I mean.

'Character' => {
'Someone' => {
'Level' => '60',
'Class' => 'Whatever',
},
}

That is how the file is laid out. Is there a way to just have it read in and build that hash? Thanks in advance.

-Alexander
 
Almost a perfect perl hash format. But I don't beleve there is anyway to use it as-is as a hash in a perl program. You could read the file and convert it to a hash, but you can do that with any file.







- Kevin, perl coder unexceptional!
 
Thanks for the reply. I figured as much and was already writing something to parse it. Just wanted to be all the way sure just in case.

-Alexander
 
That looks good to me. Just "do" the file.

test.txt:
Code:
'Character' => {
'Someone' => {
'Level' => '60',
'Class' => 'Whatever',
},
}

test.pl:
Code:
use Data::Dumper qw(Dumper);

%h = do 'test.txt';

print Dumper(\%h);

The Results:
Code:
C:\bin>perl test.pl
$VAR1 = {
          'Character' => {
                           'Someone' => {
                                          'Level' => '60',
                                          'Class' => 'Whatever'
                                        }
                         }
        };
 
I stand corrected. I tried that last night but slightly differently and it did not work. Hopefully alex1 returns to check.

- Kevin, perl coder unexceptional!
 
Thanks guys that saves lots of time.

-Alexander
 
Ok just wanted to make another note on here in case anyone else gets curious about this kind of thing. With the path MillerH put me on I found that I can do this with a variable as well using eval. This is good for me because then I can just save the output that is in nice hash format to a database , read it out and then eval it to get the hash back. Works great for what I'm doing.

Thanks again for the help.

-Alexander
 
Another way to save variables and data structures is to use Data::Dumper. Storable tends to blow up in your face if you try to manually edit the data it saved.

Code:
my $data = {
   'Character' => {
      'Someone' => {
         'Level' => '60',
         'Class' => 'Whatever',
      },
   },
};

open (SAVE, ">saved.txt");
print SAVE Dumper($data);
close (SAVE);

# and to reload the data
my $reloaded = do "saved.txt";

It saves the data structure in an easy to read format:
Code:
$VAR1 = {
   'Character' => {
      'Someone' => {
         'Level' => '60',
         'Class' => 'Whatever',
      },
   },
};

and it can be reloaded back into Perl just the same way. You can also edit the data structure manually by opening "saved.txt" and changing things around, without your script blowing up when it tries to load in the data again (unless of course you make a typo that leads to syntax errors!)

-------------
Kirsle.net | Kirsle's Programs and Projects
 
I don't think you can edit any data saved with Storable. For example, if you use Storable for:

Code:
my $data = {
   'Character' => {
      'Someone' => {
         'Level' => '60',
         'Class' => 'Whatever',
      },
   },
};

it looks like this in the file:

Code:
pst0...1234......

If you tried to edit that it probably would have a tendency to blow up.

- Kevin, perl coder unexceptional!
 
Yes, Storable is good for it's speed (optimized using C) and compactness of it's output. But it locks you into a specific implementation method, and keeps you from being able to easily and securely edit the data in alternate ways.

I therefore use Data::Dumper as well for any of my object persistence needs. I have a wrapper module for it so that the data is formatted into a single line. I prefer this since this way database selects are full of random returns when debugging information. I also use it for saving structures to the file system, and read them back just as Kirsle demonstrated.

I have two utility methods that I use during development, since they will show the initial level of a complex data structure in a formatted way, and all other levels as compact.

Code:
package Wrap::Data::Dumper;

### Creator: Miller H
###
### This module is used as a wrapper to the Data::Dumper module.  It
### formats the data into a single line.
### [URL unfurl="true"]http://perldoc.perl.org/Data/Dumper.html[/URL]

require Exporter;
*import = \&Exporter::import;
@EXPORT_OK = qw(stringify stringifyHash stringifyArray);
%EXPORT_TAGS = (all => \@EXPORT_OK);

use Data::Dumper;
use Carp;

use strict;

sub stringify ($) {
	confess("Wrong number of parameters passed") if @_ != 1;
	
	# Change the default behavior of Dumper.  The goal being
	# to compact the output.
	local $Data::Dumper::Indent		= 0;	# Default of 2
	local $Data::Dumper::Terse		= 1;	# Default of 0
	local $Data::Dumper::Quotekeys	= 0;	# Default of 1

	# Default Dumper options.  Explicitly specified here in case
	# some module overrides them without using "local"
	local $Data::Dumper::Purity = 0;
	local $Data::Dumper::Pad = '';
	local $Data::Dumper::Varname = 'VAR';
	local $Data::Dumper::Useqq = 0;
	local $Data::Dumper::Freezer = '';
	local $Data::Dumper::Toaster = '';
	local $Data::Dumper::Deepcopy = 0;
	local $Data::Dumper::Bless = 'bless';

	return Dumper(@_);
}

sub stringifyHash {
	confess("Wrong number of parameters passed") if @_ % 2;

	my @vals = ();
	for (my $i = 0; $i <= $#_; $i += 2) {
		push @vals, stringify($_[$i]) . ' => ' . stringify($_[$i+1]);
	}

	return _formatArray(@vals);
}

sub stringifyArray {
	return _formatArray(map {stringify($_)} @_);
}

# Supporting Functions
sub _formatArray {
	return @_ ? '(' . join(',', map {"\n   $_"} @_) . "\n)" : '()';
}

1;

__END__

Probably too much of a seque, but figured I'd share anyway.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top