#!/usr/bin/perl use strict; use warnings; my $EmployeeDataFilename = 'emp.dat'; my %EmployeeInfo = (); # -----[ Initialize ]----------------------------------------------------------- # We cold have also demonstrated how to code up the population of a hash from # its declarative statement above, but I felt this would make more sense to # someone new to Perl: # ------------------------------------------------------------------------------ { $EmployeeInfo{'A001'}{'FIRSTNAME'} = 'George'; $EmployeeInfo{'A001'}{'LASTNAME'} = 'Burns'; $EmployeeInfo{'A001'}{'AGE'} = 99; $EmployeeInfo{'A002'}{'FIRSTNAME'} = 'Luke'; $EmployeeInfo{'A002'}{'LASTNAME'} = 'Skywalker'; $EmployeeInfo{'A002'}{'AGE'} = 21; } # -----[ Process ]-------------------------------------------------------------- { &readEmployeeFile(); # Modify one of the elements -- pretend it's George's birthday. $EmployeeInfo{'A001'}{'AGE'}++; &writeEmployeeFile(); } exit; sub readEmployeeFile { # -------------------------------------------------------------------------- # For the simple version, we will simply load the entire file into a hash # each time, then write the whole thing back out each time. # # This is NOT efficient, will NOT scale well, and is generally a poor design # for a production product. # # It does, however, have the advantage of demonstrating a number of # necessary techniques for writing a better system without cluttering up the # process with record management logic. # -------------------------------------------------------------------------- if (!open EMPFIL, '<', $EmployeeDataFilename) { print "Cannot open input file \"$EmployeeDataFilename\"\n"; } else { # File sucessfully opened. Read all employee data and store in the hash while (my $empbuf = ) { chomp $empbuf; my ($employeeID, $lastName, $firstName, $age, $garbage) = split /\t/, $empbuf, 4; my $empkey = uc $employeeID; $EmployeeInfo{$empkey}{'LASTNAME'} = $lastName; $EmployeeInfo{$empkey}{'FIRSTNAME'} = $firstName; $EmployeeInfo{$empkey}{'AGE'} = $age; } close EMPFIL; } } sub writeEmployeeFile { # -------------------------------------------------------------------------- # For the simple version, we will simply rewrite the entire file each time # Doing otherwise requires either use of deprecated functionality, modules, # or more complex coding techniques which exceed the initial scope of # this example. # -------------------------------------------------------------------------- if (!open EMPFIL, '>', $EmployeeDataFilename) { print "Cannot open output file \"$EmployeeDataFilename\"\n"; } else { # File sucessfully opened. Write each employee data to the file foreach my $empkey (sort keys %EmployeeInfo) { print "Storing employee ID $empkey\n"; # ------------------------------------------------------------------ # First convert the hash data to a tab-separated values format # NOTE: This requires that the data contains no tabs or that a way # to encapsulate tabs is taken into consideration. To keep # this example simple, we will intentionally make the poor # engineering choice of presuming the data to have no tabs. # ------------------------------------------------------------------ my $tsvdat = &makeTsvData( $empkey, $EmployeeInfo{$empkey}{'LASTNAME'}, $EmployeeInfo{$empkey}{'FIRSTNAME'}, $EmployeeInfo{$empkey}{'AGE'} ); # Now converted to a single line of text, write the data to the file print EMPFIL "$tsvdat\n"; } close EMPFIL; } } # -----[ makeTsvData() ]-------------------------------------------------------- # This is a largely-useless subroutine, but it could be moulded into something # very useful. Right now it presumes exactly four parameters, knows what they # are supposed to be, and the only service it really provides is converting any # undef values to blank or zero depending on whether it is intended as string or # numeric. The crux of the routine is the join statement, which could simply # have been done in the main code, but I wanted to demonstrate the ability to # use a subroutine to perform more complex data validation and manipulation # without muddying up your main script. This is kept deliberately simple as it # is meant to be an example to inspire other uses and to demonstrate the # technique; in the real world, I would have made this routine much more generic # and much more robust. # ------------------------------------------------------------------------------ sub makeTsvData { my ($employeeID, $lastName, $firstName, $age) = @_; # Cleans the input if (!defined $employeeID) { $employeeID = ''; } if (!defined $lastName) { $lastName = ''; } if (!defined $firstName) { $firstName = ''; } if (!defined $age) { $age = 0; } my $tsvData = join "\t", $employeeID, $lastName, $firstName, $age; return $tsvData; } __END__ #### #!/usr/bin/perl use strict; use warnings; my $EmployeeDataFilename = 'emp.dat'; my %EmployeeInfo = (); { if (!open EMPFIL, '<', $EmployeeDataFilename) { print "Cannot open input file \"$EmployeeDataFilename\"\n"; } else { # File sucessfully opened. Read all employee data and store in the hash while (my $empbuf = ) { chomp $empbuf; my ($employeeID, $lastName, $firstName, $age, $garbage) = split /\t/, $empbuf, 4; my $empkey = uc $employeeID; $EmployeeInfo{$empkey}{'LASTNAME'} = $lastName; $EmployeeInfo{$empkey}{'FIRSTNAME'} = $firstName; $EmployeeInfo{$empkey}{'AGE'} = $age; print "\n"; print "Employee ID: $employeeID\n"; print " Name: $firstName $lastName\n"; print " Age: $age\n"; } close EMPFIL; } } __END__