Eu preparei este exemplo com o Mojo :: UserAgent . Para a entrada CSV, usei vários conjuntos de dados do NYC Open Data . Isso também aparecerá na próxima atualização para Mojo Web Clients .
Eu construo a solicitação sem fazer a solicitação imediatamente, e isso me dá o objeto de transação $tx
,. Posso substituir o read
evento para enviar imediatamente as linhas para Text :: CSV_XS :
#!perl
use v5.10;
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;
my $url = ...;
my $tx = $ua->build_tx( GET => $url );
$tx->res->content->unsubscribe('read')->on(read => sub {
state $csv = do {
require Text::CSV_XS;
Text::CSV_XS->new;
};
state $buffer;
state $reader = do {
open my $r, '<:encoding(UTF-8)', \$buffer;
$r;
};
my ($content, $bytes) = @_;
$buffer .= $bytes;
while (my $row = $csv->getline($reader) ) {
say join ':', $row->@[2,4];
}
});
$tx = $ua->start($tx);
Isso não é tão bom quanto eu gostaria, porque todos os dados ainda aparecem no buffer. Isso é um pouco mais atraente, mas é frágil da maneira que observo nos comentários. No momento, sou muito preguiçoso para melhorar, porque isso fica muito rápido quando você descobre que possui dados suficientes para processar um registro. Meu código específico não é tão importante quanto a idéia de que você pode fazer o que quiser, pois o transator lê dados e os passa para o manipulador de conteúdo:
use v5.10;
use strict;
use warnings;
use feature qw(signatures);
no warnings qw(experimental::signatures);
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new;
my $url = ...;
my $tx = $ua->build_tx( GET => $url );
$tx->res->content
->unsubscribe('read')
->on( read => process_bytes_factory() );
$tx = $ua->start($tx);
sub process_bytes_factory {
return sub ( $content, $bytes ) {
state $csv = do {
require Text::CSV_XS;
Text::CSV_XS->new( { decode_utf8 => 1 } );
};
state $buffer = '';
state $line_no = 0;
$buffer .= $bytes;
# fragile if the entire content does not end in a
# newline (or whatever the line ending is)
my $last_line_incomplete = $buffer !~ /\n\z/;
# will not work if the format allows embedded newlines
my @lines = split /\n/, $buffer;
$buffer = pop @lines if $last_line_incomplete;
foreach my $line ( @lines ) {
my $status = $csv->parse($line);
my @row = $csv->fields;
say join ':', $line_no++, @row[2,4];
}
};
}