我想出了以下方法来检查换行符的 $scaler 的最后一个字符:
if( $buffer !~ /\n$/ ) {
if( substr( $buffer, -1, 1 ) !~ /\n/ ) {
if( substr( $buffer, -1, 1 ) ne '\n' ) {
我有更快的方法吗?$buffer 标量的大小可能会变大,我注意到它越大,这些条件运行的时间就越长。如果有帮助的话,我确实有另一个包含 $buffer 长度的标量。
谢谢
完整代码:
#!/usr/bin/perl
use strict;
use warnings;
use Fcntl qw();
use Time::HiRes qw( gettimeofday tv_interval );
use constant BUFSIZE => 2 ** 21; # 2MB worked best for me, YMMV.
die "ERROR: Missing filename" if( !$ARGV[0] );
my $top = [gettimeofday];
sysopen( my $fh, $ARGV[0], Fcntl::O_RDONLY | Fcntl::O_BINARY ) or
die "ERROR: Unable to open $ARGV[0], because $!\n";
open my $output, ">", "/dev/null"; # for 'dummy' processing
my $size = -s $ARGV[0];
my $osiz = $size;
my( $buffer, $offset, $lnCtr ) = ( "", "", 0 );
while( $size ) {
my $read = sysread( $fh, $buffer, BUFSIZE, length($offset) );
$size -= $read;
my @lines = split /\n/, $buffer;
if( substr( $buffer, -1, 1 ) ne "\n" ) {
$offset = pop( @lines );
} else {
$offset = "";
}
for my $line ( @lines ) {
processLine( \$line );
$lnCtr++;
}
$buffer = $offset if( $offset );
}
close $fh;
print "Processed $lnCtr lines ($osiz bytes) in file: $ARGV[0] in ".
tv_interval( $top ).
" secs.\n";
print "Using a buffered read of ".BUFSIZE." bytes. - JLB\n";
sub processLine {
if( ref($_[0]) ) {
print $output ${$_[0]}."\n";
} else {
print $output $_[0]."\n";
}
return 0;
}
我想我已经达到了“收益递减点”,因为我试图让这个运行更快。它现在似乎能够像我的 RAID5 SSD 一样快地读取数据。如您所见,我没有使用 chomp() 是有原因的,输入可以包含数十万个换行符,我需要保留这些换行符以便能够换行进行处理。
./fastread.pl newdata.log 在文件中处理了 516670 行(106642635 字节):newdata.log 在 0.674738 秒内。使用 2097152 字节的缓冲读取。- 捷豹路虎