Чтение из дополняемого файла

Проблема

Требуется читать данные из непрерывно растущего файла, однако при достижении конца файла (текущего) следующие попытки чтения завершаются неудачей.

Решение

Читайте данные, пока не будет достигнут конец файла. Сделайте паузу, сбросьте флаг EOF и прочитайте новую порцию данных. Повторяйте, пока процесс не пpeрвется. Флаг EOF сбрасывается либо функцией seek:
for (;;) {
  while (<FH>) { .... }
  sleep $SOMETIME;
  seek(FH, 0, 1);
}
либо методом clearerr модуля IO::Handle:
use IO::Seekable;
for (;;)  {
  while (<FH>) { .... }
  sleep $SOMETIME;
  FH->clearerr();
}

Комментарий

При достижении конца файла во время чтения устанавливается внутренний флаг, который препятствует дальнейшему чтению. Для сброса этого флага проще всего воспользоваться методом clearerr, если он поддерживается (присутствует в модулях IO::Handle и FileHandle). Кроме того, можно вызвать метод POSIX: : clearerr:
$naptime = 1;
use IO::Handle;
open (LOGFILE, "/tmp/logfile") or die "can't open /tmp/logfile: $!";
for (;;) {
  while (<LOGFILE>) { print }  # Или другая операция
  sleep $naptime;
  LOGFILE->clearerr();         # Сбросить флаг ошибки ввода/вывода
}
Если простейший вариант в вашей системе не работает, воспользуйтесь функцией seek. Приведенный выше фрагмент с seek пытается переместиться на 0 байт от текущей позиции, что почти всегда завершается успехом. Текущая позиция при этом не изменяется, но зато для манипулятора сбрасывается признак конца файла, благодаря чему при следующем вызове <LOGFILE> будут прочитаны новые данные.
Если и этот вариант не работает (например, из-за того, что он полагается на так называемую «стандартную» реализацию ввода/вывода библиотек С), попробуйте следующий фрагмент — он явно запоминает старую позицию в файле и напрямую возвращается к ней:
for (;;)  {
  for ($curpos = tell(LOGFILE); <LOGFILE>; $curpos = tell(LOGFILE)) {
    # Обработать $_
  }
  sleep $naptime;
  seek(LOGFILE, $curpos, 0);     # Вернуться к прежней позиции
}
Некоторые файловые системы позволяют удалить файл во время чтения из него. Вероятно, в таких случаях нет смысла продолжать работу с файлом. Чтобы программа в подобных ситуациях завершалась, вызовите stat для манипулятора и убедитесь в том, что количество ссылок на него (третье поле возвращаемого списка) не стало равным нулю:
exit if (stat(LOGFILE))[3] == 0
Модуль File::stat позволяет записать то же самое в более понятном виде:
use File: :stat;
exit if stat(*LOGFILE)->nlink == 0;

См. также

Описание функции seek



2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: