2011-08-02 9 views
1

私はファイルに日付を挿入するためにカレンダーファイルを読んでおり、日付は日付順に保持します。問題は、日付がどこにあるのかを見つけると、ファイルがすでに挿入したい点を過ぎて見ているときです。Perlでファイルポインタを操作する方法

# November 2010 
11/26/2010 
11/27/2010 
11/28/2010 
11/29/2010 
11/30/2010 
# December 
12/24/2010 
12/25/2010 
12/26/2010 
12/27/2010 
12/28/2010 
12/29/2010 
12/30/2010 

と私のコードは次のようになります:

私が探していたカレンダーファイルは、次のようになりますどのように、前を指すようにするよう

while (my $line = <FILE>) { 
    if (substr($line, 0, 1) =~ m/\#/ || $line =~ m/calendar/) { #if the line is commented out or contains the calendar's name skip to next line 
     next; 
    } 
    chomp($line); 
    my ($temp_month, $temp_day, $temp_year) = split(/\//, $line, 3); 
    if ($year == $temp_year && $month == $temp_month && $day < $temp_day) { 
     ? 
    } 
} 

だから何か提案がある

ファイル内にスポットがありますか?

+0

なぜ新しいファイルに日付をプリントするだけではないのですか?それで、あなたは正しい順序で印刷文を簡単に置くことができます。 – TLP

答えて

0

標準のperlのソリューションは、問題のメモリを投げることです。

 
open(my $FILE, ....); #open in read/write mode 
my @lines = <FILE>;  #slurp in all lines of file 
... insert (or delete?) into array ... 
truncate($FILE, 0); #if deleting, you will need to truncate 
seek($FILE, 0, 0); 
print $FILE @lines; 

あなただけではなく、すべてより変化点から書くことができますが、スピードが重要でない場合は、シンプルさはあまり持って、より効率的にバグの可能性。

+2

並行処理に関する懸念がある場合は、新しいファイルを書き込んだ後、元のファイル名に変更する方が良いでしょう。 – ErikR

+0

並行処理の問題が発生した場合は、名前を変更するよりもロックが有効です。しかし、すべての場合において、ロックと名前の変更はより安全です。 – Gilbert

2

seekおよびtellは巻き戻しの問題を解決します。既存の行を上書きすることになります。怠け者の解決策は、Tie::Fileを使用することです。もう1つの可能性は、新しいバージョンを書き出している間にファイルを読み込んだり、完了したら古いバージョンを新しいバージョンに置き換えたりすることです。

3

これは、Tie::Fileモジュールの大きな用途のようです。ファイルを配列のように扱うことができ、ファイルポインタの現在の位置を気にする必要はありません。また、ファイル全体をメモリに読み込むことにも依存しないので、大量のファイルを扱うことができます。

use Tie::File; 

tie @array, 'Tie::File', $file; 

for (my $i =0; $i <= @array; $i++) { 
    if (/date comparison/*see note below) { 
     splice @array, $i, 0, $new_date; 
    } 
} 

これにより、spliceのようなperlの配列関数を使用して改行を挿入することができます。

しかし、日付比較戦略にも大きな問題があります。月、年を組み合わせてファイルに日付がない場合はどうなりますか?あなたはループし、その場所を見つけることはありません。 timelocalをチェックしてください。両方の日付をエポックタイムに変換して比較することができます。

use Time::Local; 
my $temp_epoch = timelocal(0,0,0,$temp_day,$temp_month -1, $temp_year-1900); 
if ($epoch < $temp_epoch) { 
    ... 
} 
関連する問題