Text-CSV_XS
view release on metacpan or search on metacpan
$cboi = undef;
}
if ($cbai) {
my $cb = $cbai;
$cbai = sub { $cb->(@_); $_[0]->say ($fho, $_[1]); 0 };
}
else {
$cbai = sub { $_[0]->say ($fho, $_[1]); 0 };
}
# Put all callbacks back in place for streaming behavior
$attr{'callbacks'}{'after_parse'} = $cbai; $cbai = undef;
$attr{'callbacks'}{'before_out'} = $cbbo; $cbbo = undef;
$attr{'callbacks'}{'on_in'} = $cboi; $cboi = undef;
$attr{'callbacks'}{'on_error'} = $cboe; $cboe = undef;
$out = undef;
$sink = 1;
}
if ($out) {
if (ref $out and ("ARRAY" eq ref $out or "HASH" eq ref $out)) {
my %hash;
csv (in => $_, out => \%hash, key => "id") for sort glob "foo-[0-9]*.csv";
my @list; # List of arrays
csv (in => $_, out => \@list) for sort glob "foo-[0-9]*.csv";
my @list; # List of hashes
csv (in => $_, out => \@list, bom => 1) for sort glob "foo-[0-9]*.csv";
=head4 Streaming
X<streaming>
If B<both> C<in> and C<out> are files, file handles or globs, streaming is
enforced by injecting an C<after_parse> callback that immediately uses the
L<C<say ()>|/say> method of the same instance to output the result and then
rejects the record.
If a C<after_parse> was already passed as attribute, that will be included
in the injected call. If C<on_in> was passed and C<after_parse> was not, it
will be used instead. If both were passed, C<on_in> is ignored.
The EOL of the first record of the C<in> source is consistently used as EOL
for all records in the C<out> destination.
my $csv = Text::CSV_XS->new ({ binary => 1, eol => "\r\n" });
my $sth = $dbh->prepare ($sql); $sth->execute;
$csv->print ($fh, $sth->{NAME_lc});
while (my $row = $sth->fetch) {
$csv->print ($fh, $row);
}
# using the csv function, all in memory
csv (out => "foo.csv", in => $dbh->selectall_arrayref ($sql));
# using the csv function, streaming with callbacks
my $sth = $dbh->prepare ($sql); $sth->execute;
csv (out => "foo.csv", in => sub { $sth->fetch });
csv (out => "foo.csv", in => sub { $sth->fetchrow_hashref });
Note that this does not discriminate between "empty" values and NULL-values
from the database, as both will be the same empty field in CSV. To enable
distinction between the two, use L<C<quote_empty>|/quote_empty>.
csv (out => "foo.csv", in => sub { $sth->fetch }, quote_empty => 1);
* CR/NL/CRNL inside quoted fields not affected by strict_eol
* Fix incorrect error 2014 (issue 62)
1.59 - 2025-01-05, H.Merijn Brand
* Fixed EOL test for Windows with crnl layer
* It is 2025
1.58 - 2024-12-30, H.Merijn Brand
* Add strict_eol (warnings default in csv ())
* Add XS line number in errors
* Add streaming support - not set in stone
1.57 - 2024-11-12, H.Merijn Brand
* Keep runtime error from csv ()
* add csv (on_error)
1.56 - 2024-08-09, H.Merijn Brand
* Yet another strict/comment_str conflict (issue 57)
* Strict affected by column_names
1.55 - 2024-06-18, H.Merijn Brand
* [csv2xls/csv2xlsx] do not generate xls/xlsx on empty CSV (issue 18)
* New: support $csv->formula (sub { ... })
* Support stacked encodings
1.39 - 2019-03-15, H.Merijn Brand
* It's 2019
* Fix tests to skip on Encode failing (PR#17 charsbar + klapperl)
* Tested on Z/OS (s390x - Hercules) :)
* Test with new Module::CPANTS::Analyse
* Add options -w/-b/-Z to csvdiff
* Fix strict on streaming EOF
* Now also tested with cperl
1.38 - 2018-12-30, H.Merijn Brand
* Name the duplicate headers on error 1013
* Add missing attributes to default list (doc only, David H. Gutteridge)
* Add support for combined keys
* Look at $NO_COLOR for csvdiff
* Add support for key-value pair
1.37 - 2018-09-27, H.Merijn Brand
t/92_stream.t view on Meta::CPAN
callbacks => {
after_parse => sub {
warn ++$I, "\n";
$co->print ($fho, $_[1]);
},
},
);
}
close $tfno;
chomp @W;
is ("@W", "1 1 2 2 3 3", "Old-fashioned streaming");
}
# Basic straight-forward streaming, no filters/modifiers
unlink $tfno if -e $tfno;
csv (in => $tfni, out => $tfno, quote_space => 0);
ok (-s $tfno, "FILE -> FILE");
is_deeply (csv (in => $tfno), $aoa, "Data is equal");
unlink $tfno if -e $tfno;
open my $fho, ">", $tfno;
csv (in => $tfni, out => $fho, quote_space => 0);
close $fho;
ok (-s $tfno, "FILE -> FH");
t/92_stream.t view on Meta::CPAN
csv (
in => $tfni,
out => $tfno,
quote_space => 0,
after_parse => sub { $_[1][1] .= "X" },
);
ok (-s $tfno, "With after_parse");
my @new = map { my @x = @$_; $x[1] .= "X"; \@x } @$aoa;
is_deeply (csv (in => $tfno), \@new, "Data is equal");
# Prove streaming behavior
my $io = "";
unlink $tfno if -e $tfno;
csv (
in => $tfni,
out => $tfno,
on_in => sub { $io .= "I" },
callbacks => { before_print => sub { $io .= "O" }},
);
ok (-s $tfno, "FILE -> FILE");
is_deeply (csv (in => $tfno), $aoa, "Data is equal");
( run in 0.245 second using v1.01-cache-2.11-cpan-4d50c553e7e )