この例をMojo :: UserAgentで作りました。CSV入力には、NYC Open Dataのさまざまなデータセットを使用しました。これは、Mojo Webクライアントの次の更新でも表示される予定です。
リクエストをすぐに作成せずにリクエストを作成すると、トランザクションオブジェクトが得られます$tx
。次に、read
イベントを置き換えて、すぐに行を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);
すべてのデータがまだバッファーに表示されるので、それは私が望むほどには良くありません。これは少し魅力的ですが、コメントで指摘したように脆弱です。レコードを処理するのに十分なデータがあるとすぐにわかるので、それは非常に早く毛むくじゃらになるので、私は現時点では怠惰です。私の特定のコードは、トランザクションがデータを読み取ってコンテンツハンドラーに渡すのと同じように、好きなことを実行できるという考えほど重要ではありません。
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];
}
};
}