Событие "файл занят для записи" в Delphi/Lazarus
| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Событие "файл занят для записи" в Delphi/Lazarus

Событие "файл занят для записи" в Delphi/Lazarus

Ответ
Поиск в этой теме
Непрочитано 20.03.2013, 07:01 #1
Событие "файл занят для записи" в Delphi/Lazarus
ETCartman
 
Регистрация: 09.12.2008
Сообщений: 4,643

Здравствуйте коллеги !
есть специфический вопрос по сабжу. В рамках написания программы необходимо считывать текстовый файл с диска. До этого посылается команда другой программе для записи данных в этот файл. Объем данных и время записи может быть разным и поэтому когда я обращаюсь чтобы считать данные - иногда вылетает ошибка Access Denied. Ставлю между командой на запись и чтением некую задержку, но это не всегда срабатывает.
есть идея каким то образом организовать цикл и периодически посылать запросы к файлу - занят он или закрыт. Если открыт то выходить из цикла и считывать его . Если закрыть то ждать немного и потом опять пытаться считать. Ну и так до определенного предела времени чтобы не вызвать зависание навсегда если что то не так
есть ли какое то специальное свойство в lazarus (delphi) чтобы определить открытость/закрытость файла не вызывая ошибку?
PS замечу что запуск стороннего приложения с флагом wait не работает. Это приложение в свою очередь использует другие подпрограммы, то есть мне именно нужно получить информцию о файле с которым оно работает.
Просмотров: 9983
 
Непрочитано 20.03.2013, 07:48
#2
DEM

YngIngKllr
 
Регистрация: 29.03.2005
СПб
Сообщений: 12,968


А не лучше ли создавать БД и с ней работать...
А по части чтения надо использовать FileExists, если файл существует, но пользователь не имеет прав на его просмотр, то будет возвращено False.
Вопросы по Лазарю, лучше тут задавать или тут...
__________________
Работаю за еду.
Working for food.
Für Essen arbeiten.
العمل من أجل الغذاء
Працую за їжу.
DEM вне форума  
 
Непрочитано 20.03.2013, 08:46
#3
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


@ETCartman
Можно конечно и на форуме домохозяек задавать вопросы о Delphi/Lazarus, однако всё же разумнее это делать на специализированных форумах (если ты действительно заинтересован в том, чтобы получить качественный ответ).

По теме: приложение, которое должно читать полученный результат, может самостоятельно запустить др. приложение, которое будет формировать файл. Как только запущенный процесс будет завершён, программа может продолжить работу, считывая сгенерированный файл. В этом-то какая сложность?
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:

Последний раз редактировалось hwd, 20.03.2013 в 08:55.
hwd вне форума  
 
Автор темы   Непрочитано 20.03.2013, 09:08
#4
ETCartman


 
Регистрация: 09.12.2008
Сообщений: 4,643


ну насчет домохозяек это напрасно. хотя я конечно попробую задать на спец. форуме если не получится
вот тут пример. если не нажимать open - файл читается. если нажать - нет. даже закрыть его без ошибки нельзя.
скорее всего я где то напортачил.
Вложения
Тип файла: zip test.zip (64.0 Кб, 59 просмотров)
ETCartman вне форума  
 
Непрочитано 20.03.2013, 09:36
#5
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,372


Не здесь надо спрашивать. Решения легко находятся поиском по ReadDirectoryChanges - это специальная функция WinAPI. Применить её не так просто, но примеры есть. Легко найдутся.


Никакого "события" или "свойства" отркытости в Delphi/Lasarus, естественно, нет. Но есть замечательная конструкция try.... except...end. Она предназначена как раз для предотвращения ошибок. Т.е. поместив действие с файлом, при котором может произойти ошибка в "ловушку", как раз и предотвращаем последствия.

Код:
[Выделить все]
 try
// пытаемся что-то сделать
except
// что делать при ошибке. Может просто пусто быть, если ничего не делать.
end;
Задержку надо делать в своей программе не через wait, а через Timer. В событии OnTimerTimer помещаются какие-то периодические действия. Например "стучаться" в файл. Для простеньких случаев это сойдет.

Надо учитывать, что совсем не обязательно файл, в который кто-то пишет, может быть недоступен. Это зависит от программы, которая его открыла. Например Notepad++ не блокирует открытые им файлы, в них можно писать. Но он следит, не изменился ли файл. А другие программы блокируют.

Для серьезной работы лучше пользоваться приличными библиотеками. Для Delphi просто обязательны бесплатная Jedi (JCL + JVCL). Там найдется 90% всех необходимых визуальных компонент и модулей на все случаи жизни любителя. В том числе для грамотной работы с файлами. Когда посмотришь, как люди в течение многих лет работают над казалось бы простыми действиями (например скопировать файл), понимаешь разницу между самоделкинским и профессиональным кодированием.

Для совсем серьезной работы с файловой системой лучше всего использовать библиотеки VirtualShellTools от Mustangpeak. Там есть всё - и визуальное и невизуальное. Пример NamespaceBrowser показывает, сколько интимных подробностей можно узнать про любой файл.
ShaggyDoc вне форума  
 
Непрочитано 20.03.2013, 10:26
#6
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Offtop:
Цитата:
Сообщение от ShaggyDoc Посмотреть сообщение
Но есть замечательная конструкция try.... except...end. Она предназначена как раз для предотвращения ошибок.
Любопытства ради: влияет ли в Delphi данная конструкция на скорость работы приложения, в случае частого возникновения исключений? Если влияет, то насколько сильно? Например, в .NET за возможность обработки исключений приходится платить существенным снижением скорости работы приложения (в случае частого возникновения Exception).
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 20.03.2013, 12:46
#7
ShaggyDoc

Thượng Tá Quân Đội Nhân Dân Việt Nam
 
Регистрация: 14.03.2005
44d32'44"С, 33d26'51"В
Сообщений: 13,372


Цитата:
влияет ли в Delphi данная конструкция на скорость работы приложения, в случае частого возникновения исключений
Конечно влияет, как в любой системе программирования. Это же всего удобная лишь языковая конструкция, которая может заменить массу рутинных проверок. Но ошибочные ситуации бывают разные, они вызывают кучу последовательных событий как в ОС, так и в разных библиотеках и в самой программе. На всё требуется время. А как именно повлияет, уже от ума программиста зависит. Можно, например, не заботиться вообще об делении на ноль, спрятав за обработчик. Но машина-то будет "дергаться" (условно говорю) часто. А можно заранее позаботиться о контроле данных ещё до операции деления. Тогда ловушка будет очень редко срабатывать.

Применять надо там, где предугадать ошибку невозможно. Например, при обращении к БД могут быть всякие сбои, никак от программы не зависящие (да связь разорвалась) - тут обязательно надо предусматривать. Если для Connection установлен timeout, так и тормозить будет сильно. Но я не замечаю вообще ощутимых торможений в своих программах, хоть ловушки часто ставлю. Просто они редко срабатывают. Еще зависит и от того, что в except...end записано.
ShaggyDoc вне форума  
 
Непрочитано 20.03.2013, 12:57
#8
Танатос


 
Регистрация: 14.03.2013
Сообщений: 9


А может тогда проще сделать, если файл нужен только на чтение, проверить есть ли он, и скопировать под другим именем.
Дальше произвести все необходимые действия и сохранить под другим именем, насколько я понимаю, ETCartman делает какой то конвертер...
Танатос вне форума  
 
Непрочитано 20.03.2013, 12:59
#9
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Offtop: Помнится когда-то сравнивал результаты итераций различными способами по базе данных чертежа, содержащей 736 323 примитива. Один из вариантов был с обработкой исключений (самый долгий), второй - через PInvoke (средний по скорости) и третий - без возникновения исключений (самый быстрый). Разница была колоссальной (результаты здесь).
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 20.03.2013, 20:55
#10
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


ETCartman
1. Стоит забыть о доступе к файлам через файловые переменные. Используйте FileOpen\FileClose и доступ к файлу по хэндлу (по хендлу возвращаемому FileOpen понятно открылся файл или нет) или потоки.
2. Ошибка у вас в коде изза повторного открытия незакрытого файла - Button2Click оставляет файл открытым, все остальные процедуры перед своими действиями пытаются повторно открыть файл. Нормальная практика работы с файлом: открыл-прочитал\записал-закрыл, ненадо его постоянно открывать\закрывать и размазывать открытие и закрытие по разным кускам кода.

hwd
>>Разница была колоссальной (результаты здесь).
конечно try/except замедляет код и пользовать его стоит для "глобальных" действий, а не заворачивая каждую "элементарную" операцию отдельно.
zamtmn вне форума  
 
Непрочитано 20.03.2013, 21:04
#11
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от zamtmn Посмотреть сообщение
пользовать его стоит для "глобальных" действий, а не заворачивая каждую "элементарную" операцию отдельно.
Совершенно неверное заявление.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 20.03.2013, 21:14
#12
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


Если забить на
>>Разница была колоссальной
то да))
zamtmn вне форума  
 
Непрочитано 20.03.2013, 21:17
#13
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от zamtmn Посмотреть сообщение
Если забить на
>>Разница была колоссальной
то да))
Нет, просто достаточно подумать немного и сразу станет понятно почему обозначенное заявление неверно.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 20.03.2013, 21:27
#14
DEM

YngIngKllr
 
Регистрация: 29.03.2005
СПб
Сообщений: 12,968


zamtmn
У него файл открыт в совершенно другой проге, он делает конвертер......
Вот он и хочет получать из него актуальную инфу...
Проще всего наверное сохранить в той проге в которой он работает, и дальше запускать и считывать информацию своей прогой...
Файл при этом наверное все таки лучше скопировать и прочитать...
__________________
Работаю за еду.
Working for food.
Für Essen arbeiten.
العمل من أجل الغذاء
Працую за їжу.
DEM вне форума  
 
Непрочитано 20.03.2013, 21:42
#15
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


DEM
Я написал в общем о работе с файлами и причине ошибки.
>>Проще всего наверное...
Хз. случаи бывают разные))

hwd
Давай подумаем вместе))
zamtmn вне форума  
 
Непрочитано 20.03.2013, 21:49
#16
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от zamtmn Посмотреть сообщение
hwd
Давай подумаем вместе))
Ну давай... Конкретный пример, варианты решения которого я показывал по ссылке: нужно получить валидные идентификаторы всех не удалённых объектов базы данных чертежа. Предположим, что в нашем арсенале нет недокументированного метода Database.TryGetObjectId, а так же нет возможности воспользоваться P/Invoke. Однако на руках имеется документированный метод Database.GetObjectId, который позволяет получить ObjectId на основе Handle, если для указанного хэндла идентификатор существует, иначе - генерируется исключение. Думай, с помощью каких глобальных" действий ты решишь эту задачу? Мой вариант решения ты знаешь.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 20.03.2013, 22:08
#17
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


Нет. так думать я немогу, т.к. по ссылке не ходил и .нет не умею.
я всего лишь имел ввиду что лучше
Код:
[Выделить все]
try
for i=0 to много
  делаем_чтото_простое;
except
// что делать при ошибке. Может просто пусто быть, если ничего не делать.
end;
чем
Код:
[Выделить все]
for i=0 to много
begin
  try
    делаем_чтото_простое;
  except
  // что делать при ошибке. Может просто пусто быть, если ничего не делать.
  end;
end;
т.е. насколько "бесплатной" бы обработка исключений не была - при необдуманном использовании она может хорошо отъесть производительность программы
Описаное тобой - попытка использовать обработку ошибок как возврат значения из функции - может и оправданный способ в рамках отсутствия функций и недокументированности API, но по сути частный случай и стрельба по пушкам из воробъев))

Последний раз редактировалось zamtmn, 20.03.2013 в 22:18.
zamtmn вне форума  
 
Непрочитано 20.03.2013, 22:17
#18
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от zamtmn Посмотреть сообщение
Описаное тобой - попытка использовать обработку ошибок как возврат значения из функции - может и оправданный способ в рамках отсутствия функций и недокументированности API, но по сути стрельба по пушкам из воробъев))
Всё зависит от контекста решаемой задачи. В той, что я привёл тебе выше, если в try/catch взять цикл целиком, то результат будет неверным, т.к. цикл будет прерван при обнаружении первого же недействительного хэндла и, как следствие, полученный набор идентификаторов будет далеко не полным, т.е. мы получим некорректный ответ. С др. стороны, если мы поместим в try/catch непосредственно операцию получения идентификатора, которую мы выполняем в цикле многократно, то в случае возникновения исключения мы просто игнорируем полученную ошибку и переходим к очередному витку нашего цикла, не прерывая его. Второй вариант будет работать очень медленно в виду того, что в процессе работы цикла будет сгенерировано несколько сотен исключений, однако результат будет корректным - мы получим идентификаторы всех объектов БД.

Мораль здесь проста: try\catch нужно использовать не по принципу "глобальных действий", и не по принципу " заворачивания каждой элементарной операции", а определять это исходя их конкретных случаев, ориентируясь на получение корректного результата (в приоритете).
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
 
Непрочитано 20.03.2013, 22:40
#19
zamtmn

КИПиА
 
Регистрация: 21.03.2005
Tyumen
Сообщений: 1,352
<phrase 1=


hwd
Моя мораль не сложнее: обработку ошибок нужно использовать для обработки ошибок, остальное - от лукавого, хотя иногда приходится выкручиваться.
В описаном случае надо требовать у автодеска чтоб Database.GetObjectId в случае отсутствия примитива возвращал какойнибудь EObjectIdInvalid или задокументировать предназначенную для этого недокументируемую функцию. Привиденные мной куски псевдокода кода к решаемой тобой задаче не имеют отношения, это просто пример
zamtmn вне форума  
 
Непрочитано 20.03.2013, 22:48
#20
hwd

C, C++, C#
 
Регистрация: 07.10.2009
С-Пб.
Сообщений: 2,762
Отправить сообщение для hwd с помощью Skype™


Цитата:
Сообщение от zamtmn Посмотреть сообщение
надо требовать у автодеска
.
__________________
Надеюсь, ты не социальный овощ? Это определяется делами! :welcome:
hwd вне форума  
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Событие "файл занят для записи" в Delphi/Lazarus