Perl не хватает памяти - PullRequest
1 голос
/ 07 февраля 2012

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

Недостаточно памяти во время «большого» запроса на 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)";

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

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

Ответы [ 3 ]

2 голосов
/ 07 февраля 2012

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

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

1 голос
/ 07 февраля 2012

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

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

с этим:

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

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

0 голосов
/ 09 февраля 2012

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

Удалите первую close(OUT); и посмотрите, улучшится ли она.


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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...