note
Narveson
<p>I concur wholeheartedly. Use objects and encapsulate the gory details.</p>
<p>My [id://693061|earlier post] left the details out in the open. Here's how those details fit into [pc88mxer]'s framework.</p>
<blockquote><i>For each input file format (i.e. parse specification) you need to be able to create an input source object ...</i></blockquote>
<code>package RecordParser::FixedWidth;
# constructor takes the name of the source file
sub new {
my ( $class, $source ) = @_;
</code>
<readmore><code> my $template;
my @fields;
my @column_specs = lookup_specs($source);
for my $column_spec ( @column_specs ) {
my ($field, $offset, $width)
= @$column_spec{qw(field offset width)};
$template .= "\@${offset}A$width";
push @fields, $field;
}
open my $reader, '<', $source;
</code></readmore>
<blockquote><i></i></blockquote>
<code> my $obj = {
IO => $reader,
template => $template,
fields_ref => \@fields,
};
bless $obj => $class;
}
</code>
<blockquote><i>...whose ->next method will produce the next data record (or undef it there isn't any more.) </i></blockquote>
<code>sub next {
my ( $self ) = @_;
my ($reader, $template, $fields_ref)
= @$self{qw(IO template fields_ref)};
my @fields = @$fields_ref;
my $record = <$reader>;
return unless defined $record;
</code>
<readmore><code> my %value_of;
my @values = unpack($template, $record);
@value_of{@fields} = @values;
</code></readmore>
<blockquote><i>The key decision will be what to use for your data record object. A good generic choice is to use a hash-ref.</i></blockquote>
<code> return \%value_of;
}
</code>
693052
693085