如何在Perl中操作文件指针

时间:2011-08-02 11:19:50

标签: perl file-io file-pointer

因此,我正在阅读日历文件以在文件中插入日期,并且我希望日期保持按时间顺序排列。当我找到日期应该去的地方时,问题出现了,文件已经超出了我要插入的点。

我正在查看的日历文件如下所示:

# 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) {
        ?
    }
}

那么有关于如何指向文件中的上一个位置的任何建议吗?

4 个答案:

答案 0 :(得分:6)

在文件中随机移动所需的功能是seek。但是有关如何在Perl常见问题解答中解决此问题的更多信息 - How do I change, delete, or insert a line in a file, or append to the beginning of a 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;
    }
}

这将允许您使用perl的数组函数(如splice)来插入新行。

但是,您的日期比较策略也存在很大问题。如果在给定的月份,年份组合中文件中没有日期怎么办?你会循环而不是找到它的位置。查看timelocal,您可以将其用于将日期转换为纪元时间,然后进行比较。

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

答案 2 :(得分:2)

seektell将解决回卷问题。您最终将覆盖当前现有的行。懒惰的解决方案是使用Tie::File,这是另一种可能,它在写出新版本时读取文件,然后在完成时用新版本替换旧版本。

答案 3 :(得分: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;

为了提高效率,你可以从变化的角度而不是一切来写,但如果速度不重要,简单就有较少的bug潜力。