2011-12-18 15 views
7

Büyük dosyadaki belirli satırları belleğe yüklemeden hızlı ve bellek açısından verimli bir yol var mı?Perl'deki büyük dosyadan belirli bir satırın okunması

Çok sayıda çatal çalıştıran bir perl komut dosyası yazdım ve bunların bir dosyadan belirli satırları okumasını istiyorum. Harici komutunu kullanarak şu Im anda

:

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; 
} 

Onun hızlı ve çalışır - hızlı ve bunun gibi verimli bellek gibi daha "Perl-imsi" yol, ama belki orada?

Bildiğiniz gibi, Perl'de bir çatal işlemi oluşturmak ana işlem belleğini kopyalar - böylece ana işlem 10MB kullanıyorsa, çatal en az o kadar kullanır.

Amacım, çatal işlemini (böylece çatalları çalıştırana kadar ana işlem) bellek kullanımını mümkün olduğunca düşük tutmaktır. Bu yüzden tüm dosyayı belleğe yüklemek istemiyorum.

+2

btw, ''IGNORE_' değil' IGNORE' değil. – ikegami

cevap

16

Daha ileri gitmeden önce, fork'un nasıl çalıştığını anlamak önemlidir. Bir süreçte, fork bir işletim sistemi olduğunda, ana öğe ve alt işlemlerin belleğini toplu olarak paylaşmak için copy-on-write semantik kullanır; Ebeveyn ve çocuk arasında farklılık gösteren hafıza miktarı ayrı olarak tahsis edilmelidir.

open my $fh, '<', $filePath or die "$filePath: $!"; 
my $line; 
while(<$fh>) { 
    if($. == $lineWanted) { 
     $line = $_; 
     last; 
    } 
} 

Bu akım dosya tanıtıcısına satır numarasını tutan özel $. değişkeni kullanır: Perl bir dosyanın tek bir satır okumak için

, burada basit bir yoludur.

4

Tie::File çekirdek modülüne bakın.

+0

"Tie :: File" bellek yetersiz olduğunu düşündüm. OP, düşük bellek kullanımını talep etmedi mi? – Zaid

+0

@Zaid aslında bellek açısından verimli; Dosyanın tüm içeriğini bellekte saklamaz, sadece her satırın * ofsetleri * listesini içerir. Ücretsiz değil (her ofsetin her satırda tutması için yeterli olan skaler bile olsa), ama genellikle yüzlerce megabaytlık dosyaları kolaylıkla halledebilecek kadar iyi. – hobbs

+0

@hobbs: Yup. O zamandan beri belgelere baktım (yorum şu anda oldukça eski) ve bunun bir bellek çenesi olmadığını açıkça ortaya koyuyor. – Zaid

0

Çatal tutmanıza gerek yoktur. Tahmin edebileceğiniz gibi, bir dosyadan belirli bir satır okumak, CPAN'ın 20k modüllerinden birinin bunu yaptığı gibi yeterli bir işlemdir.

File::ReadBackwards, bellek etkin ve hızlıdır.

İlgili konular