|
Вопрос # 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" ошибка не вылетает . пока все ок. Спасибо за помощь и за функцию, она еще пригодится.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|