App-RecordStream

 view release on metacpan or  search on metacpan

lib/App/RecordStream/Operation/fromcsv.pm  view on Meta::CPAN

package App::RecordStream::Operation::fromcsv;

our $VERSION = "4.0.25";

use strict;

use base qw(App::RecordStream::Operation);

use Text::CSV;

sub init {
  my $this = shift;
  my $args = shift;

  my @fields;
  my $header_line = undef;
  my $strict = 0;
  my $delim  = ',';
  my $escape = '"';
  my $quote  = '"';

  my $spec = {
    "keys|k|field|f=s" => sub { push @fields, split(/,/, $_[1]); },
    "header"           => \$header_line,
    "strict"           => \$strict,
    "delim|d=s"        => \$delim,
    "escape=s"         => \$escape,
    "quote=s"          => \$quote,
  };

  $this->parse_options($args, $spec);

  die "Delimiter must be a single character\n\n"
    unless length $delim == 1;

  my $csv_args = {
    binary      => 1,
    eol         => $/,
    sep_char    => $delim,
    escape_char => $escape,

    # Text::CSV wants undef, but it's easier to pass the empty string at the shell.
    quote_char  => ($quote eq '' ? undef : $quote),
  };

  if ( !$strict ) {
    $csv_args->{'allow_whitespace'}    = 1;
    $csv_args->{'allow_loose_quotes'}  = 1;
    $csv_args->{'allow_loose_escapes'} = 1;
  }

  $this->{'FIELDS'}      = \@fields;
  $this->{'HEADER_LINE'} = $header_line;
  $this->{'PARSER'}      = new Text::CSV($csv_args);
  $this->{'EXTRA_ARGS'}  = $args;
}

sub wants_input {
  return 0;
}

sub stream_done {
  my $this = shift;

  my $files = $this->{'EXTRA_ARGS'};

  if ( scalar @$files > 0 ) {
    foreach my $file ( @$files ) {
      $this->update_current_filename($file);

      open(my $fh, '<', $file) or die "Could not open file: $!\n";
      $this->get_records_from_handle($fh);
      close $fh;
    }
  }
  else {
    $this->get_records_from_handle(\*STDIN);
  }
}

sub get_records_from_handle {
  my ($this, $handle) = @_;

  my $parser     = $this->{'PARSER'};
  my $do_headers = $this->{'HEADER_LINE'};
  my @fields     = @{ $this->{'FIELDS'} };

  while(my $row = $parser->getline($handle)) {
    if ( $do_headers ) {
      push @fields, @$row;
      $do_headers = 0;
      next;
    }

    my @values = @$row;

    my $record = App::RecordStream::Record->new();
    for(my $i = 0; $i < @values; ++$i) {



( run in 1.723 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )