#########################################################
package AnyData::Format::Fixed;
#########################################################
# copyright (c) 2000, Jeff Zucker <jeff@vpservices.com>
#########################################################
=head1 NAME
AnyData::Format::Fixed - tiedhash & DBI/SQL access to Fixed length data
=head1 SYNOPSIS
use AnyData;
my $table = adHash( 'Fixed', $filename,'r',{pattern=>'A20 A2'} );
while (my $row = each %$table) {
print $row->{name},"\n" if $row->{country} =~ /us|mx|ca/;
}
# ... other tied hash operations
OR
use DBI
my $dbh = DBI->connect('dbi:AnyData:');
$dbh->func('table1','Fixed', $filename, {pattern=>'A20 A2'},'ad_catalog');
my $hits = $dbh->selectall_arrayref( qq{
SELECT name FROM table1 WHERE country = 'us'
});
# ... other DBI/SQL operations
=head1 DESCRIPTION
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.
Refer to L<http://perldoc.perl.org/functions/pack.html> for the formatting of the pattern.
Please refer to the documentation for AnyData.pm and DBD::AnyData.pm
for further details.
=head1 AUTHOR & COPYRIGHT
copyright 2000, Jeff Zucker <jeff@vpservices.com>
all rights reserved
=cut
use strict;
use warnings;
use AnyData::Format::Base;
use vars qw( @ISA $VERSION);
@AnyData::Format::Fixed::ISA = qw( AnyData::Format::Base );
$VERSION = '0.12';
sub read_fields {
my $self = shift;
my $str = shift;
if (!$self->{pattern}) {
print "NO UNPACK PATTERN SPECIFIED!"; exit;
}
my @fields = unpack $self->{pattern}, $str;
if ($self->{trim}) {
@fields = map {s/^\s+//; s/\s+$//; $_} @fields;
}
return @fields;
}
sub write_fields {
my $self = shift;
my @fields = @_;
my $fieldNum =0;
my $patternStr = $self->{pattern} || '';
$patternStr =~ s/[a-zA-Z]//gi;
my @fieldLengths = split /\s+/, $patternStr;
my $fieldStr = '';
for(@fields) {
next unless defined $_;
# PAD OR TRUNCATE DATA TO FIT WITHIN FIELD LENGTHS
my $oldLen = length $_ || 0;
my $newLen = $fieldLengths[$fieldNum] || 0;
if ($oldLen < $newLen) { $_ = sprintf "%-${newLen}s",$_; }
if ($oldLen > $newLen) { $_ = substr $_, 0, $newLen; }
$fieldNum++;
$fieldStr .= $_;
}
$fieldStr .= $self->{record_sep};
#print "<$fieldStr>";
return $fieldStr;
}
1;