Как манипулировать указателем файла в Perl - PullRequest
1 голос
/ 02 августа 2011

Итак, я читаю файл календаря, чтобы вставить дату в файл, и я хочу, чтобы даты оставались в хронологическом порядке. Проблема возникает, когда я нахожу место, куда должна идти дата, файл уже просматривает точку, в которую я хочу вставить.

Файл календаря, на который я смотрю, выглядит так:

# 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 ]

6 голосов
/ 02 августа 2011

Функция, которая вам нужна для случайного перемещения по файлу: seek .Но есть больше информации о том, как решить эту проблему в Perl FAQ - Как изменить, удалить или вставить строку в файл или добавить в начало файла?

3 голосов
/ 02 августа 2011

Звучит как отличное применение для модуля 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 голосов
/ 02 августа 2011

seek и скажи решат проблему возврата.В итоге вы перезапишете существующие строки.Ленивое решение состоит в том, чтобы использовать Tie :: File , еще одну возможность - прочитать файл при записи новой версии, а затем заменить старую версию новой, когда вы закончите.

0 голосов
/ 02 августа 2011

Стандартное решение 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;

Чтобы быть более эффективным, вы могли бы просто писать с точки изменения, а не со всего, но если скорость не важна, простота имеетменьше ошибок.

...