Ich habe dieses Beispiel mit Mojo :: UserAgent erstellt . Für die CSV-Eingabe habe ich verschiedene Datensätze aus den NYC Open Data verwendet . Dies wird auch im nächsten Update für Mojo Web Clients angezeigt .
Ich erstelle die Anfrage, ohne sie sofort zu stellen, und das gibt mir das Transaktionsobjekt $tx
. Ich kann das read
Ereignis dann ersetzen , damit ich die Zeilen sofort an Text :: CSV_XS senden kann :
#!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);
Das ist nicht so schön, wie ich es gerne hätte, weil alle Daten immer noch im Puffer angezeigt werden. Dies ist etwas ansprechender, aber es ist fragil in der Art, wie ich es in den Kommentaren notiere. Ich bin im Moment zu faul, um es besser zu machen, weil das sehr schnell haarig wird, wenn Sie herausfinden, wann Sie genug Daten haben, um einen Datensatz zu verarbeiten. Mein spezieller Code ist nicht so wichtig wie die Idee, dass Sie tun können, was Sie möchten, während der Transaktor Daten liest und an den Inhaltshandler weitergibt:
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];
}
};
}