| 
| 
 | Вопрос # 4 336/ вопрос открыт / | 
 |  Здравствуйте, уважаемые эксперты!Такая ситуация: есть лог файл, который постоянно дописывается (его ведет сторонняя программа, периодически его дописывая с разным интервалом времени ).  Так как нет определенного времени по которому она дописывает файл , приходится его всегда читать.  Возникает проблема, если читать в тот момент когда происходит запись, вылетает ошибка  "raised exception class EInOutError witch message 'I/O error 32".
 Возможно ли определить момент записи файла сторонней программой и в этот момент не читать? Либо другие способы для решения этой проблемы.
 
|  |   Вопрос задал: mr_switch (статус: Посетитель)Вопрос отправлен: 17 июня 2010, 05:00
 Состояние вопроса: открыт, ответов: 2.
 |  Ответ #1. Отвечает эксперт: Егор Здравствуйте, mr_switch!Можно выключать выдачу исключений с помощью команд {$1-} / {$i+}, а проверку успешности открытия файла осуществлять с помомщьдю функции IOResult (подход, свойственный Паскалю):
 
 ...
{$I-} // выключили прерывания по ошибкам ввода-вывода
      // пробелы перед открывающей фигурной скобкой в начале строки должны отсутствовать!
  ... // здесь попытались открыть файл
{$I+} // включили обратно прерывания по ошибкам ввода-вывода
  if IOResult=0 then // если ошибок при открытии не было
    begin
      ... // код обработки файла
    end
  else
    begin
      ... // код обработки ошибки открытия файла
    end;
...Другой подход, свойственный программированию под дельфи - обернуть "опасный" участок в блок try...except или try...finally:
 
 ...
  try
    ... // открываем файл, обрабатываем его
  except
    on EInOutError do
      begin
        ... // открыть файл не удалось. здесь обрабатываем ошибку
      end;
  end;
|  | Ответ отправил: Егор (статус: 10-ый класс)Время отправки: 17 июня 2010, 05:30
 Оценка за ответ: 4
 Комментарий к оценке: все та же ошибка вылетает |  Ответ #2. Отвечает эксперт: min@y™ Вот это КОД!!! Лучше б не показывал! Убери его отсюда, не позорься. А у себя в программе замени это безобразие на 
 procedure TForm1.Timer2Timer(Sender: TObject);
begin
  try
    cmd.Lines.LoadFromFile('C:\log\log.csv');
  except
    cmd.Lines.Text:= 'err open';
  end;
end;
|  | Ответ отправил: min@y™ (статус: Доктор наук)Время отправки: 17 июня 2010, 13:01
 Оценка за ответ: 4
 Комментарий к оценке: теперь вылетает такая ошибка: "raised exception class EFOpenError with message 'Cannot open file "C:\log\log.csv". Процесс не может получить доступ к файлу, так как этот файл занят другим процеccом'. |  
 Мини-форум вопросаВсего сообщений: 7; последнее сообщение — 21 июня 2010, 17:27; участников в обсуждении: 3. 
|   | Егор (статус: 10-ый класс), 17 июня 2010, 05:36 [#1]:блин, в ответе ошибся. Вот так без ошибки: "Можно выключать выдачу исключений с помощью команд {$I-} / {$I+}
 Опасайтесь багов в приведенном выше коде; я только доказал корректность, но не запускал его.— Donald E. Knuth.
 |  
|   | min@y™ (статус: Доктор наук), 17 июня 2010, 08:12 [#2]:Покажи код чтения файла. Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | mr_switch (статус: Посетитель), 17 июня 2010, 12:52 [#3]:procedure TForm1.Timer2Timer(Sender: TObject); var
 t1:TextFile;
 s:String;
 begin
 cmd.Lines.Clear;
 try
 AssignFile(t1, 'C:\log\log.csv');
 Reset(t1);
 while not(Eof(t1)) do
 begin
 Readln(t1, s);
 cmd.Lines.Add(s);
 end;
 CloseFile(t1);
 except
 on EInOutError do
 begin
 cmd.Lines.Add('err open');
 end;
 end;
 
 end;
 
 Вставил в блок try...except не помогло , все та же ошибка вылетает.
 |  
|   | mr_switch (статус: Посетитель), 18 июня 2010, 17:28 [#4]:изначально было так: procedure TForm1.Timer2Timer(Sender: TObject);
 begin
 cmd.Lines.LoadFromFile('C:\log\log.csv');
 end;
 
 потом изменил на то что выше....
 
 сейчас сделал вот-так:
 procedure TForm1.Timer2Timer(Sender: TObject);
 begin
 try
 cmd.Lines.LoadFromFile('C:\log\log.csv');
 except
 cmd.Lines.Text:= 'err open';
 end;
 end;
 
 теперь вылетает такая ошибка: "raised exception class EFOpenError with message 'Cannot open file "C:\log\log.csv". Процесс не может получить доступ к файлу, так как этот файл занят другим процеccом'.
 
 Как перед открытием файла определить, не открыт ли он другой программой ?
 |  
|   | min@y™ (статус: Доктор наук), 18 июня 2010, 17:38 [#5]: Цитата (mr_switch): теперь вылетает такая ошибка: "raised exception class EFOpenError with message 'Cannot open file "C:\log\log.csv". Процесс не может получить доступ к файлу, так как этот файл занят другим процеccом'.
 Как перед открытием файла определить, не открыт ли он другой программой ?
 
 Ну и за что 4 балла? Я же не знал, что у тебя включена галочка "Tools/Debugger options/Language exceptions/Stop on Delphi exceptions"! Я, блин, не телепат.
 Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | min@y™ (статус: Доктор наук), 18 июня 2010, 17:45 [#6]: Цитата (min@y™): Как перед открытием файла определить, не открыт ли он другой программой ?  Да хоть вот так:
 
 function FileIsOpen(const Filename: String): Boolean;
var
   Datei: TFileStream;
begin
  result:= FALSE; 
  if FileExists(Filename) then begin
    try
      Datei:= TFileStream.Create(Filename, fmOpenRead);
      Datei.Free;
    except
      on EFOpenError do result:= true;
    end;
  end;
end;Взято из Delphi works.Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп! |  
|   | mr_switch (статус: Посетитель), 21 июня 2010, 17:27 [#7]:min@y™:  убрал "Tools/Debugger options/Language exceptions/Stop on Delphi exceptions"  ошибка не вылетает . пока все ок. Спасибо за помощь и за функцию, она еще пригодится. |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |