可疑的Perl缓冲问题



我认为我有一个Perl缓冲问题,因为我需要读取和解析大的文本文件(由我自己在前几行代码中创建),最后在另一个文件中打印的东西。

在读取了包含90,855行和第二个文件的其他一些行的文件之后,脚本没有完全读取文件的一行。

我已经计算了读取的字符数,直到发生这种情况:233,467,因此尝试刷新缓冲区并在读取文件的下一行之前休眠。它不工作。

有什么建议吗?下面是我的代码:
foreach $i (@files) {
    my $buff = 0;
    print "Analyzing $in";
    sleep(1);
    $program = $1 if $i =~ /(w+)_SITES/;
    open(FIL, $i) or die "$!: $in";
    while (<FIL>) {
        $buff += length($_);
        if ($buff >= 230000) {  #FLUSH THE BUFFER, NOT WORKING!!!
            $buff = 0;
            sleep(1);
            select((select(FIL), $| = 1)[0]);
        }
        undef($a);
        unless ($. == 1) {
            if ($o == 0) {
                if (/^d+t(S+)t(S+)t(d+)t(d+)t(S+)t(S+)t(.*)/) {
                    $mirna  = $1;
                    $target = $2;
                    $start  = $3;
                    $end    = $4;
                    $site   = $5;
                    $comp_p = $6;
                    $a      = $7;
                    $j      = "${mirna}_${target}_${start}_$end";
                    $site_nu{$j} = "$mirnat$targett$startt$endt$sitet$comp_p";    # Store each site in a hash
                }
                else {   #DIES HERE!!!
                  die "$buff characters, in line $.:$_n"
                }
            }
            else {
                if (/^d+t(S+)t(S+)t(d+)t(d+)t(S+)t(.*)/) {
                    $mirna       = $1;
                    $target      = $2;
                    $start       = $3;
                    $end         = $4;
                    $site        = $5;
                    $a           = $6;
                    $j           = "${mirna}_${target}_${start}_$end";
                    $site_nu{$j} = "$mirnat$targett$startt$endt$site";    # Store each site in a hash
                }
            }

在读取第二个文件的3,413个字符后,在" dies HERE!!"处死亡。

这是因为regex不起作用,因为只有一半行在$_.

问题几乎肯定是因为数据不在文件中要读取。

您说该文件是从代码的前一部分生成的。我怀疑你有一个缓冲问题在那里。一旦代码完成了文件的写入,使用close将剩余的数据刷新到文件中,我猜一切都会好起来的。

您应该检查close呼叫的成功状态,如下所示

close FILEHANDLE or die "Unable to close temporary file: $!";

除此之外,为如此少量的数据使用临时文件而不是简单地将其全部保存在内存中是否明智值得怀疑。另外:

  • 您必须始终 use strictuse warnings,并使用my尽可能接近它们的第一个使用点来声明所有变量。除非您选择在程序的顶部声明所有内容(这是一个非常糟糕的主意),否则您没有这样做

  • 您选择的变量名不稳定。文件名是$i吗?$o代表什么?$buff将是好的,除了它是一个概念缓冲区的大小而不是缓冲区本身

  • 您应该使用三个参数形式的词法文件句柄open: open my $fil, '<', $i or die "$!: $i";

  • 如果您正确使用$|,则使用FILE->autoflush而不是交换所选文件句柄并设置$|的技巧更简洁,更具可读性。要做到这一点,您需要在代码的开头使用use IO::Handle,除非您正在运行Perl 5版本14或更高版本,该版本会根据需要加载IO::File(因此也会加载IO::Handle)

  • 我认为一个简单的split /t/会比你正在使用的正则表达式更好。它看起来也像你会更好地使用数组的散列%site_nu像这样$site_nu{$j} = [$mirna, $target, $start, $end, $site, $comp_p]

  • die字符串的末尾加一个换行符可以阻止perl显示有关源文件和数据文件以及行号的信息,这可能在您调试

  • 时很有用。
  • 你会做你自己,和那些你寻求帮助的人,格式化你的源代码很好。如果没有适当的缩进,很难判断代码块的开始和结束位置

最新更新