2013-03-31 47 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