| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | ######################################################### | 
| 2 |  |  |  |  |  |  | package AnyData::Format::Fixed; | 
| 3 |  |  |  |  |  |  | ######################################################### | 
| 4 |  |  |  |  |  |  | # copyright (c) 2000, Jeff Zucker | 
| 5 |  |  |  |  |  |  | ######################################################### | 
| 6 |  |  |  |  |  |  |  | 
| 7 |  |  |  |  |  |  | =head1 NAME | 
| 8 |  |  |  |  |  |  |  | 
| 9 |  |  |  |  |  |  | AnyData::Format::Fixed - tiedhash & DBI/SQL access to Fixed length data | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  | use AnyData; | 
| 14 |  |  |  |  |  |  | my $table = adHash( 'Fixed', $filename,'r',{pattern=>'A20 A2'} ); | 
| 15 |  |  |  |  |  |  | while (my $row = each %$table) { | 
| 16 |  |  |  |  |  |  | print $row->{name},"\n" if $row->{country} =~ /us|mx|ca/; | 
| 17 |  |  |  |  |  |  | } | 
| 18 |  |  |  |  |  |  | # ... other tied hash operations | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | OR | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | use DBI | 
| 23 |  |  |  |  |  |  | my $dbh = DBI->connect('dbi:AnyData:'); | 
| 24 |  |  |  |  |  |  | $dbh->func('table1','Fixed', $filename, {pattern=>'A20 A2'},'ad_catalog'); | 
| 25 |  |  |  |  |  |  | my $hits = $dbh->selectall_arrayref( qq{ | 
| 26 |  |  |  |  |  |  | SELECT name FROM table1 WHERE country = 'us' | 
| 27 |  |  |  |  |  |  | }); | 
| 28 |  |  |  |  |  |  | # ... other DBI/SQL operations | 
| 29 |  |  |  |  |  |  |  | 
| 30 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  | This is a parser for fixed length record files.  You must specify an unpack pattern listing the widths of the fields e.g. {pattern=>'A3 A7 A20'}.  You can either supply the column names or let the module get them for you from the first line of the file.  In either case, they should be a comma separated string. | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | Refer to L for the formatting of the pattern. | 
| 35 |  |  |  |  |  |  |  | 
| 36 |  |  |  |  |  |  | Please refer to the documentation for AnyData.pm and DBD::AnyData.pm | 
| 37 |  |  |  |  |  |  | for further details. | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  | =head1 AUTHOR & COPYRIGHT | 
| 40 |  |  |  |  |  |  |  | 
| 41 |  |  |  |  |  |  | copyright 2000, Jeff Zucker | 
| 42 |  |  |  |  |  |  | all rights reserved | 
| 43 |  |  |  |  |  |  |  | 
| 44 |  |  |  |  |  |  | =cut | 
| 45 |  |  |  |  |  |  |  | 
| 46 | 2 |  |  | 2 |  | 8 | use strict; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 51 |  | 
| 47 | 2 |  |  | 2 |  | 6 | use warnings; | 
|  | 2 |  |  |  |  | 2 |  | 
|  | 2 |  |  |  |  | 50 |  | 
| 48 | 2 |  |  | 2 |  | 309 | use AnyData::Format::Base; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 41 |  | 
| 49 | 2 |  |  | 2 |  | 8 | use vars qw( @ISA $VERSION); | 
|  | 2 |  |  |  |  | 2 |  | 
|  | 2 |  |  |  |  | 689 |  | 
| 50 |  |  |  |  |  |  | @AnyData::Format::Fixed::ISA = qw( AnyData::Format::Base ); | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | $VERSION = '0.05'; | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | sub read_fields { | 
| 55 | 34 |  |  | 34 | 0 | 30 | my $self = shift; | 
| 56 | 34 |  |  |  |  | 35 | my $str  = shift; | 
| 57 | 34 | 50 |  |  |  | 59 | if (!$self->{pattern}) { | 
| 58 | 0 |  |  |  |  | 0 | print "NO UNPACK PATTERN SPECIFIED!"; exit; | 
|  | 0 |  |  |  |  | 0 |  | 
| 59 |  |  |  |  |  |  | } | 
| 60 | 34 |  |  |  |  | 115 | my @fields = unpack $self->{pattern}, $str; | 
| 61 | 34 | 50 |  |  |  | 66 | if ($self->{trim}) { | 
| 62 | 0 |  |  |  |  | 0 | @fields = map {s/^\s+//; s/\s+$//; $_} @fields; | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 63 |  |  |  |  |  |  | } | 
| 64 | 34 |  |  |  |  | 103 | return @fields; | 
| 65 |  |  |  |  |  |  | } | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | sub write_fields { | 
| 68 | 14 |  |  | 14 | 0 | 10 | my $self   = shift; | 
| 69 | 14 |  |  |  |  | 22 | my @fields = @_; | 
| 70 | 14 |  |  |  |  | 12 | my $fieldNum =0; | 
| 71 | 14 |  | 50 |  |  | 24 | my $patternStr = $self->{pattern} || ''; | 
| 72 | 14 |  |  |  |  | 45 | $patternStr =~ s/[a-zA-Z]//gi; | 
| 73 | 14 |  |  |  |  | 38 | my @fieldLengths = split /\s+/, $patternStr; | 
| 74 | 14 |  |  |  |  | 16 | my $fieldStr = ''; | 
| 75 | 14 |  |  |  |  | 16 | for(@fields) { | 
| 76 | 34 | 50 |  |  |  | 51 | next unless defined $_; | 
| 77 |  |  |  |  |  |  | # PAD OR TRUNCATE DATA TO FIT WITHIN FIELD LENGTHS | 
| 78 | 34 |  | 50 |  |  | 59 | my $oldLen = length $_ || 0; | 
| 79 | 34 |  | 50 |  |  | 64 | my $newLen =  $fieldLengths[$fieldNum] || 0; | 
| 80 | 34 | 100 |  |  |  | 62 | if ($oldLen < $newLen) { $_ = sprintf "%-${newLen}s",$_; } | 
|  | 26 |  |  |  |  | 62 |  | 
| 81 | 34 | 100 |  |  |  | 50 | if ($oldLen > $newLen) { $_ = substr $_, 0, $newLen; } | 
|  | 2 |  |  |  |  | 5 |  | 
| 82 | 34 |  |  |  |  | 24 | $fieldNum++; | 
| 83 | 34 |  |  |  |  | 62 | $fieldStr .= $_; | 
| 84 |  |  |  |  |  |  | } | 
| 85 | 14 |  |  |  |  | 13 | $fieldStr .= $self->{record_sep}; | 
| 86 |  |  |  |  |  |  | #print "<$fieldStr>"; | 
| 87 | 14 |  |  |  |  | 43 | return $fieldStr; | 
| 88 |  |  |  |  |  |  | } | 
| 89 |  |  |  |  |  |  | 1; | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  |  | 
| 92 |  |  |  |  |  |  |  | 
| 93 |  |  |  |  |  |  |  | 
| 94 |  |  |  |  |  |  |  |