Click to See Complete Forum and Search --> : File Handles from Hash Data in Perl


gschimek
11-23-2004, 09:59 PM
I have a perl script that takes data from a web form and writes that data to different files, one file for each field in the form. I do it as follows:

if ($in{moretime} ne "") {
open MORETIME, '>> moretime.dat';
flock(MORETIME,LOCK_EX);
print MORETIME $in{moretime};
print MORETIME "\n";
close MORETIME;
}

if ($in{comments} ne "") {
open COMMENTS, '>> comments.dat';
flock(COMMENTS,LOCK_EX);
print COMMENTS $in{comments};
print COMMENTS "\n";
close COMMENTS;
}


Is it possible to create a file handle based on the name of each item in the hash. For example, can I do something like:

for ($i, $i++, $I > $in)
open $in{$i}, '>> /$in{$i}/.dat';
print blah, blah, blah
close blah, blah, blah
}

where $in{$i} above is the file handle name.

If there's a way to do that, so that a for loop could create all my file handle and then create the filenames, that'd be great. Otherwise I have to create a set of code for each file handle as above.

Anybody have any ideas?

bryan.6
11-23-2004, 10:58 PM
i think i understand what you're saying... but since it's in a for loop where you open the file, write it, then close it, wouldn't it work to do something like this, using only one FILE handle but different file names?

foreach my $i ( keys %in)
open FILE, '>> /$in{$i}/.dat';
flock(FILE,LOCK_EX);
print FILE $in{$i};
print FILE "\n";
close FILE;
}

i didn't test this though...

gschimek
11-24-2004, 10:46 AM
It appears to work great, with the addition of a { after

foreach my $i ( keys %in)

Though now it's not doing the rest of my script. Haven't figured that out yet. But thanks for the help

gschimek
11-24-2004, 12:26 PM
OK, so I can get it to work if I do this:

foreach my $i ( keys %in) {
open FILE, '>> results.dat';
flock(FILE,LOCK_EX);
print FILE $in{$i};
print FILE "\n";
close FILE;
}


It will run through each of the entries in the hash and output them to the file results.dat.

But if I try to create a different file for each set of results with the code:

foreach my $i ( keys %in) {
open FILE, '>> /$in{$i}/.dat';
flock(FILE,LOCK_EX);
print FILE $in{$i};
print FILE "\n";
close FILE;
}


It doesn't output anything. I don't get any errors, but I also don't get the output.

I'm pretty sure my problem is that I haven't coded tha end of the open FILE... line correctly. What it should do is, if %in has 3 sets of entries with key values of a, b, and c. I want it to print the corresponding data for each key into 3 separate files: a.dat b.dat and c.dat

Any suggestions?

bwkaz
11-24-2004, 02:24 PM
I don't do much Perl, but maybe this would help?

foreach my $i ( keys %in) {
open FILE, '>> /' . $in{$i} . '.dat';
flock(FILE,LOCK_EX);
print FILE $in{$i};
print FILE "\n";
close FILE;
} I.e., keep almost everything the same, just use string concatenation?

Actually, it should probably be something like this:

foreach my $i ( keys %in) {
open FILE, '>> /' . $i . '.dat';
flock(FILE,LOCK_EX);
print FILE $in{$i};
print FILE "\n";
close FILE;
} instead, so that the files are named a.dat, b.dat, and c.dat instead of (data mapped to a).dat, (data mapped to b).dat, etc. Also, there's an extra slash in your original, after the $in{$i} part.

Maybe also add a few "or die <some error>" bits to some of those lines? Like the open one, for example.

gschimek
11-24-2004, 04:13 PM
I tried the concatenating and it did the same as when I did it like this:

foreach my $i ( keys %in) {
open FILE, '>> $in \.dat';
flock(FILE,LOCK_EX);
print FILE $in{$i};
print FILE "\n";
close FILE;
}

and got the info written to one file called $in.dat. I'm assuming it's because of the single parenthesis.

So then I tried double quotes


foreach my $i ( keys %in) {
open FILE, ">> $in \.dat";
flock(FILE,LOCK_EX);
print FILE $in{$i};
print FILE "\n";
close FILE;
}

and got the data written to one file called name=Joe&address=10ParkPlace&phone=555-1212...

So then I tried something that I figured wouldn't work:

foreach my $i ( keys %in) {
open FILE, ">> $in{$i} \.dat";
flock(FILE,LOCK_EX);
print FILE $in{$i};
print FILE "\n";
close FILE;
}

and I got a lot of files name the same as the contents of the hash. I figured it would do that, but at least it proves that it's stepping through the foreach loop correctly.

So why won't it print out the key names for the filenames? It obviously prints out the key values for the filenames. I know I'm close, but can't quite get there.

Any help is appreciated.

gschimek
11-24-2004, 05:49 PM
I think I figured out the problem, but it doesn't help me find a solution. In Perl, $in is completely different that $in{}. One is a variable, and one is an item in a Hash. How do I get it to print the key name as a filename, though?

bwkaz
11-24-2004, 07:44 PM
The key is $i (your for loop says "foreach my $i (keys %in)" -- the loop index is $i).

gschimek
11-25-2004, 10:53 AM
Thanks!! Works perfectly now. I did:


foreach my $i (keys %in) {
open FILE, ">> $i\.dat" or DIE || "Can't open File";
flock(FILE,LOCK_EX);
print FILE $in{$i};
print FILE "\n";
close FILE;
}


Thanks for all the help.