2013-03-31 46 views
-1

我想我有一个Perl缓冲问题,因为我需要读取和解析大文本文件(由我自己在代码的以前的行中创建)来最终在另一个文件中打印文件。可疑的Perl缓冲问题

在某个点,读取与90855行的文件和其他一些该第二文件的后,该脚本不读取行的文件的完全。

我已读计数的字符数,直到发生这种情况:233467,并且因此试图读取文件的下一行之前以冲洗缓冲液和睡眠。它不起作用。

有什么建议吗?

这里是我的代码:

foreach $i (@files) { 

    my $buff = 0; 

    print "Analyzing $i\n"; 
    sleep(1); 
    $program = $1 if $i =~ /(\w+)_SITES/; 

    open(FIL, $i) or die "$!: $i\n"; 
    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} = "$mirna\t$target\t$start\t$end\t$site\t$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} = "$mirna\t$target\t$start\t$end\t$site"; # Store each site in a hash 
       } 
      } 

它死在了 “死亡在这里!”在阅读第二个文件的3,413个字符之后死亡。

这是因为正则表达式不起作用,因为只有一半的行在$ _中。

+0

该脚本是单线程的吗? – Glenn

+0

变量'$ |'控制每个'print'语句后自动刷新*输出文件*。它对输入文件没有影响,并且输入文件的刷新没有意义。 – Borodin

+0

如果您试图读取一个制表符分隔的文件,您可以查看['Text :: CSV'](http://search.cpan.org/perldoc?Text%3A%3ACSV)。你还应该加上'use strict;使用警告;'到这个脚本并修复错误/警告。然后重写代码,使用'my'关键字将所有变量的范围缩小到最小。 – TLP

回答

2

问题几乎肯定是因为数据不在您的文件中进行读取。

你说文件是从你的代码的早期部分产生的。我怀疑你有缓冲问题代替。一旦你的代码完成了文件的写入,使用close来清除剩余的数据到文件,这是我的猜测,一切都会好起来的。

您应该检查你的close调用的成功状态,这样

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

除此之外,使用临时文件数据的这样一个小ampount,而不是智慧只是保持它的所有内存是值得怀疑的。另外:

  • 您必须总是use strictuse warnings,并宣布采用my尽可能接近要利用自己的第一个点的所有变量。除非您选择在申报程序的顶部一切(一个非常糟糕的主意),你有没有做过这

  • 你选择的变量名是不稳定的。 $i作为文件名?和$o为 - 呃 - 东西?如果您正在使用open my $fil, '<', $i or die "$!: $i";

  • $buff是除了它是一个概念上的buffre而不是缓冲区的大小 istelf

  • 你应该使用词法文件句柄与open三个参数的形式罚款$|正确,它更整洁,更易于使用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的这在你正在调试的时候可能会很有用

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

+0

感谢您的评论,伙计们。是的,我严格使用警告,并使用my声明变量,并在完成打印后成功关闭所有文件。我已经检查过,数据确实在要读取的文件中。我会尝试所有其他建议,我会尽快回复您。非常感谢。 – dannyjmh

+0

大家好。最后,在开始解析文件和解决问题之前,我刷新了我使用的输出文件句柄。非常感谢你的帮助。 – dannyjmh

+0

@dannyjmh:那么你不能正确关闭它。关闭文件比刷新它更好。您还必须在程序开始时在大块中声明变量,这不是一个好主意。 – Borodin