是否有任何快速且内存有效的方法来读取大文件的特定行,而不将其加载到内存中?
我写了一个perl脚本,它运行许多forks,我希望他们从文件中读取特定的行。
目前我正在使用外部命令:
sub getFileLine {
my ( $filePath, $lineWanted ) = @_;
$SIG{PIPE} = '_IGNORE_';
open( my $fh, '-|:utf8', "tail -q -n +$lineWanted \"$filePath\" | head -n 1" );
my $line = <$fh>;
close $fh;
chomp( $line );
return $line;
}
它的速度很快而且很有效 - 但也许有更多的“Perl-ish”方式,与这个一样快速和内存效率?
如您所知,在Perl中创建fork进程会复制主进程内存 - 因此如果主进程使用10MB,则fork将使用至少那么多。
我的目标是保持fork进程(所以主要进程直到运行forks)内存使用尽可能低。这就是为什么我不想将整个文件加载到内存中。
答案 0 :(得分:17)
在进一步了解之前,了解fork
的工作原理非常重要。当您fork
进程时,操作系统使用copy-on-write语义来共享大部分父进程和子进程&#39;记忆;只需要单独分配父和子之间不同的内存量。
要在Perl中读取文件的一行,这里有一个简单的方法:
open my $fh, '<', $filePath or die "$filePath: $!";
my $line;
while( <$fh> ) {
if( $. == $lineWanted ) {
$line = $_;
last;
}
}
这使用特殊的$.
变量,该变量保存当前文件句柄的行号。
答案 1 :(得分:4)
查看Tie::File核心模块。
答案 2 :(得分:0)
你不需要分叉。您可以想象,从文件中读取特定行是一项非常常见的操作,CPAN上的20k模块之一就已经完成。
File::ReadBackwards具有内存效率和速度。