2012-02-07 3 views
1

У меня есть сценарий, который читает два файла csv и сравнивает их, чтобы узнать, появляется ли ID, который появляется в нем, и в другом. Ошибка я получаю следующим образом:Perl Out Of Memory

Из памяти во время «большой» запрос на 67112960 байт, общая sbrk() составляет 348203008 байт

А теперь код:

use strict; 
use File::Basename; 

my $DAT  = $ARGV[0]; 
my $OPT  = $ARGV[1]; 

my $beg_doc = $ARGV[2]; 
my $end_doc = $ARGV[3]; 

my $doc_counter = 0; 
my $page_counter = 0; 
my %opt_beg_docs; 
my %beg_docs; 

my ($fname, $dir, $suffix) = fileparse($DAT, qr/\.[^.]*/); 
my $outfile = $dir . $fname . "._IMGLOG"; 

open(OPT, "<$OPT"); 
    while(<OPT>){ 
     my @OPT_Line = split(/,/, $_); 
     $beg_docs{@OPT_Line[0]} = "Y" if(@OPT_Line[3] eq "Y"); 
     $opt_beg_docs{@OPT_Line[0]} = "Y"; 
    } 
close(OPT); 
open(OUT, ">$outfile"); 
while((my $key, my $value) = each %opt_beg_docs){ 

    print OUT "$key\n"; 
} 
close(OUT); 

open(DAT, "<$DAT"); 

    readline(DAT); #skips header line 
    while(<DAT>){ 

     $_ =~ s/\xFE//g; 

     my @DAT_Line = split(/\x14/, $_); 

     #gets the prefix and the range of the beg and end docs 
     (my $pre = @DAT_Line[$beg_doc]) =~ s/[0-9]//g; 
     (my $beg = @DAT_Line[$beg_doc]) =~ s/\D//g; 
     (my $end = @DAT_Line[$end_doc]) =~ s/\D//g; 

     #print OUT "BEGDOC: $beg ENDDOC: $end\n"; 

     foreach($beg .. $end){ 
      my $doc_id = $pre . $_; 

      if($opt_beg_docs{$doc_id} ne "Y"){ 
       if($beg_docs{$doc_id} ne "Y"){ 
        print OUT "$doc_id,DOCUMENT NOT FOUND IN OPT FILE\n"; 
        $doc_counter++; 
       } else { 
        print OUT "$doc_id,PAGE NOT FOUND IN OPT FILE\n"; 
        $page_counter++; 
       } 
      } 
     } 
    } 
close(DAT); 
close(OUT); 

print "Found $page_counter missing pages and $doc_counter missing document(s)"; 

В основном я получаю все ID из файла, который я проверяю, чтобы проверить, существует ли идентификатор. Затем я перебираю и генерирую идентификаторы для другого файла, потому что они представлены как диапазон. Затем я беру сгенерированный идентификатор и проверяю его в хэше ID.

забыл также отметить, я использую Windows,

+2

В чем вопрос? – vol7ron

+0

При разработке кода Perl всегда следует включать предупреждения (использовать предупреждения). – tadmc

+0

@tadmc будет делать ... Позвольте мне посмотреть, что произойдет потом. –

ответ

1

Я не уверен, если это является причиной вашей ошибки, но внутри цикла, где вы читаете DAT, вы, вероятно, хотите, чтобы заменить это:

 (my $pre = @DAT_Line[$beg_doc]) =~ s/[0-9]//g; 

с этим:

 (my $pre = $DAT_Line[$beg_doc]) =~ s/[0-9]//g; 

и то же самое для двух других линий там.

+1

Доступ к элементам массива с помощью @ вместо $ будет генерировать предупреждение, но в противном случае это должно быть хорошо. – JackTheRandom

2

Вы не используете use warnings;, вы не проверять на наличие ошибок при открытии файлов, и вы не печатает отладочные заявления с указанием строки, которые вы читаете в.

Вы знаете, что вход файл выглядит? Если у него нет разрывов строк, вы читаете весь файл сразу, что будет катастрофическим, если оно велико. Обратите внимание на то, как вы разбираете файл.

0

Вы закрываете свой дескриптор файла OUT, а затем пытаетесь распечатать его внутри цикла DAT, который, я думаю, может выводиться в случайную память, так как вы закрыли FILEHANDLE, - удивил, что это не выдало ошибку.

Снимите первые close(OUT); и убедитесь, что это улучшилось.


Я до сих пор не знаю, каков ваш вопрос, если речь идет об ошибке, это означает, что у вас закончилась нехватка памяти. Если речь идет о самом сообщении - вы пытаетесь потреблять слишком много памяти. Если это то, что вы потребляете слишком много памяти, я бы сначала спросил, читаете ли вы мое сообщение выше, затем я спрашиваю, сколько памяти у вашей системы, затем я буду следить за тем, будет ли это улучшаться, если вы возьмете повторное выражение.