Страницы: 1 2 вся ветка
Форум: "Потрепаться";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.22;
Скачать: [xml.tar.bz2];




Вниз

как определить- закончена перекачка файла или нет? 


Van   (2002-03-11 11:40) [0]

Есть задача:
при изменении каталога с картинками отображать находящиеся в нем картинки,
при этом возникает проблема - если файл большой и перекачивается долго обработчик начинает его открывать до полной перекачки - возникает ошибка. Ставить задержку - не красиво, наверняка есть более элегантный способ. FileExists не работает.
Кто знает как определить закончена-ли перекачка файла?
Всем заранее благодарен.



Polevi   (2002-03-11 11:42) [1]

а как ты его качаешь



Shaman_Naydak   (2002-03-11 12:07) [2]

открывай файл для отображения в эксклюзиве.. если открылся, значит никто его не трогаеть, во



Van   (2002-03-11 13:31) [3]

В эксклюзиве - это как (прошу извинить чайника), какой-то параметр при открытии установить? Какой, если, не трудно подскажите.

А по поводу качания (для Polevi)- качаться может по сети или через COM порт, а может и через USB, собственно это не важно. Важно что задержка есть и она не определена.



Polevi   (2002-03-11 13:44) [4]

в имени файла передавай его размер :-)



Van   (2002-03-11 14:08) [5]

Передавать размер файла в имени - дело хорошее, но я не имею доступа к передающей программе. Кроме того как опрдеделить размер файла если он еще не перекачался?

Вот Shaman_Naydak предлагает похоже дело
> открывай файл для отображения в эксклюзиве.. если открылся,
> значит никто его не трогаеть, во

, но я что-то не врублюсь как открыть в эксклюзиве, может API-я функция какая-то есть, но я ее не знаю.



Van   (2002-03-11 15:23) [6]

Похоже врубаюсь, буду пробовать.



Shaman_Naydak   (2002-03-11 15:27) [7]

>> Van
Скажи мне как ты открываешь файл, подскажу какие флаги выставить



Polevi   (2002-03-11 15:54) [8]

Shaman_Naydak © дело говорит
Если файл еше не докачен - он открыт операционной системой...



Van   (2002-03-11 16:14) [9]

Всем спасибо.
Наконец-то разобрался.
Проще всего оказалось сделать так:

repeat //проверка занятости файла
HndFile:=FileOpen(SR.Name,fmShareExclusive);
Sleep(1);
until HndFile<>-1;
FileClose(HndFile);



Юрий Зотов   (2002-03-11 18:30) [10]

FindFirst/Next/CloseChangeNotification - ожидание завершения записи файла.



Suntechnic   (2002-03-12 08:23) [11]

>Юрий Зотов © (11.03.02 18:30)
Использовать FindFirstChangeNotification(and etc.) не получится. Т.к. они не смогут проинформировать об окончании записи файла, они срабатывают в момент начала записи.

>Van (11.03.02 16:14)
Проще то оно проще, но это не самое эффективное решение. Всё дело в том, что данный цикл будет просто "забивать" процессор. Sleep(1) конечно немного облегчит дело, но явно в ущерб твоему потоку (ставить большую задержку тоже плохо, так как если это основной поток процесса, то процесс просто будет казаться зависшим в периоды ожидания). Конечно, может овчинка выделки и не стоит, но если делать всё красиво, то тебе самому надо читать файл с помощью ReadFileEx и использовать Wait-ф-ции.



panov   (2002-03-12 11:33) [12]

>Suntechnic © (12.03.02 08:23)
Использовать FindFirstChangeNotification(and etc.) не получится. Т.к. они не смогут проинформировать об окончании записи файла, они срабатывают в момент начала записи.

FILE_NOTIFY_CHANGE_SIZE
Any file-size change in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change in file size only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.
FILE_NOTIFY_CHANGE_LAST_WRITE Any change to the last write-time of files in the watched directory or subtree causes a change notification wait operation to return. The operating system detects a change to the last write-time only when the file is written to the disk. For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed.



Юрий Зотов   (2002-03-12 11:52) [13]

> Suntechnic © (12.03.02 08:23)
> они срабатывают в момент начала записи.

Если бы это было так... Как легко тогда перехватывалась бы любое изменение любого файла любой программой, несмотря на кэширование. Но увы!

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

Но для данной задачи (см. вопрос) это как раз то, что и нужно.



Van   (2002-03-12 13:14) [14]


> Suntechnic © (12.03.02 08:23)


> Проще то оно проще, но это не самое эффективное решение.
> Всё дело в том, что данный цикл будет просто "забивать"
> процессор. Sleep(1) конечно немного облегчит дело, но явно
> в ущерб твоему потоку (ставить большую задержку тоже плохо,
> так как если это основной поток процесса, то процесс просто
> будет казаться зависшим в периоды ожидания). Конечно, может
> овчинка выделки и не стоит, но если делать всё красиво,
> то тебе самому надо читать файл с помощью ReadFileEx и использовать
> Wait-ф-ции.

Спасибо за подсказку. Возможно я использую функцию ReadFileEx позже, а пока меня вполне устраивает то как я сделал. Конечно цикл и Sleep останавливают мой поток, но в данном случае мне это не важно.



Suntechnic   (2002-03-12 16:18) [15]

>Юрий Зотов © (12.03.02 11:52)
>Согласно документации, они срабатывают в момент сброса файла на диск. На практике - в момент его закрытия пишущей >программой, в чем уже пришлось убедиться. Несложно проверить, рекомендую...

Я именно и писал Вам про практику. Как понятно из названия уведомления, оно произойдёт когда изменится размер файла(трактовка в грубом приближении, конечно). Запустите проводник и проэкспериментируйте. Попробуйте скопировать большой файл из одной папки в другую. Сначала будет создан файл, а затем начнётся его копирование. И посмотрите в этот момент размер этого файла. А заодно и попробуйте поймать это уведомление. Вообщем Вы сами попробуйте... Так что для данной задачи это как раз и не подойдёт...

>panov © (12.03.02 11:33)
А по-русски мог ёшь? Хелпы читать я и так умею, хотелось бы с живими людьми пообщаться, если им конечно есть что сказать...



panov   (2002-03-12 16:30) [16]

>Suntechnic © (12.03.02 16:18)
Если по русски, то вот здесь:
http://delphi.mastak.ru/articles/panov/index.html - 2.4. Создание Execute

Достаточно указать соответствующие параметры в функции FindFirstChangeNotification



Юрий Зотов   (2002-03-12 16:44) [17]

> Suntechnic © (12.03.02 16:18)


1.
> Как понятно из названия уведомления, оно произойдёт когда
> изменится размер файла

Но не ранее, чем файл будет закрыт и сброшен на диск. Это и в хелпе написано, и на практике так и есть.


2.
> Сначала будет создан файл, а затем начнётся его копирование

И все это время файл будет ОТКРЫТ. Поэтому уведомлений не поступит, несмотря на якобы увеличивающийся размер. А по завершении копирования файл будет ЗАКРЫТ - вот в этот момент и поступит уведомление. Что и требовалось автору вопроса.


3.
> Вообщем Вы сами попробуйте...

Докладываю - делал это многократно. Пробовать еще раз не вижу смысла.


4.
> Так что для данной задачи это как раз и не подойдёт...

Как раз для данной задачи - отловить момент завершения копирования - это именно то, что нужно (см. п. 2).



Suntechnic   (2002-03-12 18:07) [18]

>Юрий Зотов © (12.03.02 16:44)
>И все это время файл будет ОТКРЫТ. Поэтому уведомлений не поступит, несмотря на якобы увеличивающийся размер.

Должен Вам заметить, если Вы ещё не в курсе, что никакой размер увеличивать не будет. Он увеличится только один раз: в момент начала копирования. Потому как нет смысла копировать файл, а потом вдруг выяснить, что места на диске нет... Поэтому сначала на диске резервируют место, а уж затем производят копирование как таковое.

>Но не ранее, чем файл будет закрыт и сброшен на диск. Это и в хелпе написано, и на практике так и есть.

Неправда. Необязательно файл должен быть закрыт, чтобы произошло уведомление об изменении его размера. А в хеле написано буквально следующее
The operating system detects a change in file size only when the file is written to the disk.
Фраза is written это не есть file must be closed. Это можно понимать,и как то, что файл должен физически существовать. Что вкладывалось в это понятие я рассуждать не хочу, тем более, что вопрос не заключается в обсуждении работы FindFirstChangeNotification, а лишь в том, можно её использовать или нет....

>Докладываю - делал это многократно. Пробовать еще раз не вижу смысла

А вот это Вы зря. Если вам конечно лень, я могу и сам вам тестовый примерчик набрасать. С двумя проектами, один будет следить, а другой писать, чтобы вы лично убедились когда всё-таки происходит уведомление от FindFirstChangeNotification. Но если это и произойдёт то только на VC++, потому как для меня на Delphi будет дольше.

>panov © (12.03.02 16:30)
К твоей демагогии я уже просто привык, так что no comments



panov   (2002-03-12 18:15) [19]

>Suntechnic © (12.03.02 18:07
Должен Вам заметить, если Вы ещё не в курсе, что никакой размер увеличивать не будет. Он увеличится только один раз: в момент начала копирования. Потому как нет смысла копировать файл, а потом вдруг выяснить, что места на диске нет... Поэтому сначала на диске резервируют место, а уж затем производят копирование как таковое.

Полная чушь. ( без комментариев)

А вот это Вы зря. Если вам конечно лень, я могу и сам вам тестовый примерчик набрасать.

Да ради бога, хоть на C.

И я, и Ю.Зотов это УЖЕ попробовали сделать.

К твоей демагогии я уже просто привык, так что no comments

Когда успел?



Suntechnic   (2002-03-12 18:28) [20]

> panov © (12.03.02 18:15)
>Полная чушь. (без комментариев)

Очередная демагогия(no comments)



Suntechnic   (2002-03-12 18:49) [21]

>Юрий Зотов © (12.03.02 16:44)
В Delphi переведёте сами:

Первый проект следит за директорией с:\temp

Код:

DWORD dwWaitStatus;
HANDLE dwChangeHandle;


dwChangeHandle = FindFirstChangeNotification(
"C:\\temp", // directory to watch
FALSE, // do not watch the subtree
FILE_NOTIFY_CHANGE_SIZE);

if (dwChangeHandle == INVALID_HANDLE_VALUE)
ExitProcess(GetLastError());


while (TRUE)
{

// Wait for notification.

dwWaitStatus = WaitForSingleObject( dwChangeHandle, INFINITE);

switch (dwWaitStatus)
{
case WAIT_OBJECT_0:
if ( FindNextChangeNotification( dwChangeHandle) == FALSE )
ExitProcess(GetLastError());
break;

default:
ExitProcess(GetLastError());
}
}


Второй проект манипуляции с файлом:

HANDLE hf = CreateFile("C:\\temp\\bigfile.big", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
SetFilePointer(hf, 1048576, 0, FILE_BEGIN);
SetEndOfFile(hf);// Notification right after this line!!!!! File is still open
CloseHandle(hf);


Как я упоминал ранее мы сначала резервируем место на диске, а копирование будем производить позже. Например сразу после строчки SetEndOfFile(hf) мы выполним SetFilePointer(hf, 0, 0, FILE_BEGIN); И начнём писать с помощью WriteFile. В итоге: событие получено, файл реально на диск не записан.

Переведите в Delphi расставьте breakpoint-ы и сами посмотрите, что за чем происходит.



panov   (2002-03-12 18:58) [22]

Нужно только правильно воспользоваться вышеописанной функцией.

Чтобы определить, кто демагог, достаточно заменить
FILE_NOTIFY_CHANGE_SIZE на
FILE_NOTIFY_CHANGE_LAST_WRITE



panov   (2002-03-12 19:00) [23]

могу даже выслать готовый проект (использовался для статьи), чтобы убедиться, что все работает, как следует.



Suntechnic   (2002-03-12 19:10) [24]

>panov © (12.03.02 18:58)
Да не надо мне ничего высылать. Ты мой примерчик переведи в Delphi и ставь там, что душа пожелает: хоть FILE_NOTIFY_CHANGE_SIZE, хоть FILE_NOTIFY_CHANGE_LAST_WRITE... Только я тебя прошу. Не надо лишних слов. Запусти мой пример и посмотри.



Юрий Зотов   (2002-03-12 22:50) [25]

Перевел, а заодно убрал лишнее. Вот код для желающих:

Монитор:

program Project1;
{$APPTYPE CONSOLE}

uses
Windows;

var
dwChangeHandle: THandle;

begin
dwChangeHandle := FindFirstChangeNotification("D:\Temp", False, FILE_NOTIFY_CHANGE_SIZE);
if dwChangeHandle <> INVALID_HANDLE_VALUE then
try
while WaitForSingleObject(dwChangeHandle, INFINITE) = WAIT_OBJECT_0 do
begin
WriteLn("Notification!");
FindNextChangeNotification(dwChangeHandle)
end
finally
FindCloseChangeNotification(dwChangeHandle)
end
end.


Пишущая программа:

procedure TForm1.FormCreate(Sender: TObject);
begin
WinExec("..\SMonitor\Project1.exe", SW_SHOWNORMAL)
end;

procedure TForm1.Button1Click(Sender: TObject);
var
H: THandle;
begin
H := CreateFile("D:\Temp\TestFile.tst", GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_RANDOM_ACCESS, 0);
try
SetFilePointer(H, 1048576, nil, FILE_BEGIN);
SetEndOfFile(H)
finally
CloseHandle(H)
end
end;

Запустил под W2K. Действительно, все работает так, как Вы сказали. Но есть одно маленькое "но".

После выпонения SetEndOfFile файл на диске УЖЕ реально существует и его размер равен заказанному - а это значит, что система УЖЕ сбросила его на диск.

О чем я и говорил - уведомление приходит В МОМЕНТ РЕАЛЬНОЙ ЗАПИСИ ФАЙЛА. Не записи в файл, а записи САМОГО файла.

То же самое сказано и в хелпе. Расшифровка простая:
"For operating systems that use extensive caching, detection occurs only when the cache is sufficiently flushed".

Просто после выполнения SetEndOfFile система решила, что пора сбрасывать кэш - вот уведомление и возникло.

В прежних моих программах эта ситуация возникала в момент закрытия файла. Хотя, конечно, очевидно, что система может сбросить кэш не только при закрытии - что мы и видели.



Suntechnic   (2002-03-12 23:03) [26]

>Юрий Зотов © (12.03.02 22:50)
>После выпонения SetEndOfFile файл на диске УЖЕ реально существует и его размер равен заказанному - а это значит, что система УЖЕ сбросила его на диск.

В этом то и суть проблемы. Т.е. файл реально существует. Размер его равен исходному. Но данных там нет!!! Данные будут записаны позже. Такое происходит не всегда, но Explorer именно так и производит копирование и пермещение файлов, так что всё-таки думаю автора вопроса этот вариант не устроит.



panov   (2002-03-13 07:14) [27]

>Suntechnic ©
>Юрий Зотов ©
Заменив FILE_NOTIFY_CHANGE_SIZE на
FILE_NOTIFY_CHANGE_LAST_WRITE,
получим в точности тот результат, который нужен,
т.к. время последнего изменения файла будет записано системой только после закрытия файла.



Suntechnic   (2002-03-13 07:46) [28]

>panov © (13.03.02 07:14)
У меня нет слов :(
Многоуважаемый Панов! Не вводите в заблуждение участников форума. Если после всего сказанного, написанного и продемонстрированного у тебя остались какие-то сомнения, то оставь их при себе. Я конечно прошу прощения за подобные высказывания в публичном форуме, но когда на чёрное говорят белое, это уже чересчур. Ладно мне ты не доверяешь(даже с написанным примером), но к мнению Юрия Зотова ты вроде должен прислушаться!?



panov   (2002-03-13 09:46) [29]

У меня нет сомнений, так как программа, что написана у меня, выполняет НУЖНУЮ работу КАК НУЖНО.
Закончим флейм и останемся при своем мнении.

А до оскорблений скатываться в публичном, как Вы изволили заметить, форуме, по меньшей мере неэтично.

PS.

Желающие могут протестировать 2 программы, написанные Suntechnic © и мной, и вынести беспристрастную оценку.

Не привожу свой код здесь, так как задача реализована как проект для демонстрации работы потоков, и его достаточно много.



panov   (2002-03-13 09:56) [30]

>Suntechnic ©
Еще хочу заметить, что Вы привели код, который не работает.
После этого, Вы утверждаете, что задача не решается.

У меня задача решена.

Так вызывается функция:

HandleChange :=
FindFirstChangeNotification(
PChar(FPath),
False,
FILE_NOTIFY_CHANGE_LAST_WRITE);

Так записывается файл:

for i := 0 to 100000 do
begin
FileWrite(FileHandle,Buf,1024);
Application.ProcessMessages;
end;



Юрий Зотов   (2002-03-13 10:48) [31]

Есть новая информация по сабжу, но это вечером - сейчас некогда.



Suntechnic   (2002-03-13 15:39) [32]

>panov © (13.03.02 09:56)
>Еще хочу заметить, что Вы привели код, который не работает.

Хватит нести ерунду. У меня работает, у Юрия Зотова работает, а у тебя вдруг нет.... это даже не смешно.

От своего примера ты получаешь желаемый результат, только потому что написал его так, чтобы получить желаемый результат...

Умение признавать свои ошибки порой ценится гораздо выше, чем умение их не делать. Вы, товарищ Панов, уже достаточно немолодой, а эту истину так и не усвоили... что ж... это ваш крест, вам его и нести...

И последнее:

"ОСКОРБИТЬ, блю, бишь; блённый (ён, ена); сов., кого-что. Тяжело обидеть, унизить." (С.И. Ожегов "Толковый словарь русского языка")

Если вы, после данной дискуссии, оказались тяжело обиженным или униженным, то я конечно же прошу прощения.



Юрий Зотов   (2002-03-13 15:48) [33]

Перестаньте ссориться - оба правы, у каждого его код правильно работает. И я тоже прав, у меня тоже все работает. Вечером расскажу, в чем дело.



panov   (2002-03-13 16:01) [34]

>Suntechnic © (13.03.02 15:39)
Да, я написал его так, чтобы он работал, чтобы получить желаемый результат.
Вы же не удосужились вникнуть в это.
А разве не это требовалось?
Или требовалось просто РАСТОПЫРИТЬ ПАЛЬЦЫ ВЕЕРОМ?

Еще раз повторяю.
Метод, используемый в panov © (13.03.02 09:56),
решает поставленную задачу.

Ваш метод доказательства нелогичен.

Раз этой функцией я не могу воспользоваться так, чтобы решить поставленную задачу, значит этой функцией воспользоваться нельзя.

И ведите дискуссию, пожалуйста. Вы не на базаре.



Andrey   (2002-03-13 16:04) [35]

>Юрий Зотов © (13.03.02 15:48)

Пришли евреи к старому равину.
- Это мой баран. - говорит один еврей.
- Нет! Это мой баран. - говорит другой еврей.
- Вы оба правы. - отвечает равин.
- Но этого не может быть. - восклицает третий еврей.
- И ты прав. - отвечает мудрый равин.

P.S. Извените, вырвалось ;)



Suntechnic   (2002-03-13 16:15) [36]

>panov © (13.03.02 16:01)
Мне надоело доказывать кому-либо, что либо. Ещё раз повторяю: с помощью этой ф-ции решить задачу в общем случае нельзя. В частном(при наложении опеределённых условий на запись файла) можно. Если вы сами не удосужились вникнуть, нечего в этом обвинять других. Попробуйте написать пример, удовлетворяющий условиям задачи(задача это не то, что вы себе придумали, а то, что спрашивал автор вопроса), когда упрётесь в стену, тогда до вас и дойдёт. Вообщем я более не собираюсь вести бесполезных споров, если у Юрия Зотова есть конструктивная информация, я готов её обсудить. С вами товарищ Панов дискутировать по поводу этой задачи я более не намерен.

P.S.
>panov ©
Кстати, Вы получали моё письмо относительно статьи?



panov   (2002-03-13 16:35) [37]

>Suntechnic © (13.03.02 16:15)
Письмо получил и сразу ответил.



Suntechnic   (2002-03-13 17:07) [38]

>panov © (13.03.02 16:35)
>Письмо получил и сразу ответил.
??? ...странно... я ничего не получал...



panov   (2002-03-13 17:21) [39]

>Suntechnic © (13.03.02 17:07)
Умение признавать свои ошибки порой ценится гораздо выше, чем умение их не делать...
Для того, для того, чтобы признать ошибку, нужно понять, в чем она состоит.

Приношу свои извинения, если мои попытки выяснить истину Вас оскорбили.

Действительно, уведомление системы возникает при сбрасывании буферов на диск и при изменении позиции указателя файла.

Моя первая ошибка была в том, что я испытывал другой метод записи, при котором FILE_NOTIFY_CHANGE_LAST_WRITE возникает только при закрытии файла.

Вторая ошибка - тестирование на NTFS, которую WinMe, конечно, не поддерживает.
Для NTFS в этом случае прекасно работает уведомление FILE_NOTIFY_CHANGE_LAST_ACCESS, использование которого решает задачу.

Похоже, у Ю. Зотова, все-таки, есть мысли, как решить эту задачу. Подождем...



Юрий Зотов   (2002-03-13 18:53) [40]

Ну, вот, выкроил окошко...

Как я уже говорил, я тестировал код Suntechnic под W2K и получил совсем не те результаты, которые получал ранее, работая под 9х. Поэтому я решил прогнать его еще раз дома, под ME.

Результаты оказались ТОЧНО такими же, что я получал и ранее - уведомления _SIZE и _LAST_WRITE приходят в момент закрытия файла. То есть, не после SetEndOfFile, а после CloseHandle - проход под отладчиком это четко показывает. В этот же момент сам файл появляется на диске.

Вывод напрашивается - уведомление, как и написано в хелпе, в любом случае приходит В МОМЕНТ РЕАЛЬНОЙ ЗАПИСИ ФАЙЛА НА ДИСК. Но линейки NT и 9х (или NTFS и FAT ?) по-разному определяют, когда следует сбрасывать кэш - отсюда и различия. В случает NT кэш сбрасывается по SetEndOfFile, а в случае 9х - по CloseHandle.

В этом и была причина наших разногласий - каждый утверждал то, что видел собственными глазами, но мы использовали разные платформы. Теперь вернемся к исходной задаче - как определить момент окончания копирования.

Думаю, что это все же возможно. Под 9х должен сработать тот код, который я уже приводил (с заменой _SIZE на _LAST_WRITE), а под NT можно вызвать ReadDirectoryChangesW (или просто перечитать каталог - это вообще железный способ, хотя и тупой), уточнить, что именно изменилось и либо ждать дальше, либо нет. Проверка платформы тоже не проблема.

Вот такие пироги. Если выкрою время, попробую набросать реально работающий код. А в свете последнего постинга panov"а есть смысл сначала проверить _LAST_ACCESS - возможно, все окажется совсем просто.

Есть конструктивные мнения? Только конструктивные , pls.



Suntechnic   (2002-03-13 21:39) [41]

>Юрий Зотов © (13.03.02 18:53)
Ок. Конструктивные, так конструктивные :)

Всё, что я буду дальше говорить будет относиться к вот такой конструкции записии в файл:

HANDLE hf = CreateFile("C:\\temp\\file.dat", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, NULL);
SetFilePointer(hf, total_file_size, 0, FILE_BEGIN);
SetEndOfFile(hf);
SetFilePointer(hf, 0, 0, FILE_BEGIN);
...
WriteFile(hf,...); // здесь происходят многократные вызовы WriteFile в цикле
...
CloseHandle(hf);


На практике файлы именно так и копируются, если Вы понаблюдаете за Explorer-ом то Вы со мной должны согласится.

Наша задача: Определить в какой момент произойдёт запись последнего байта с данными файл. Теоретически это событие должно произойти на строчке CloseHandle(hf);

Про Win98/ME сказать ничего не могу. Вынужден Вам поверить потому как на работе Win2000, дома XP, у тестеров конечно могу поросить потестить на Win98, но боюсь что меня не поймут :)

Итак с Win98 пытаемся разобраться с 2000. Пробуем вариант предложенный panov-ым © (13.03.02 17:21) с FILE_NOTIFY_CHANGE_LAST_ACCESS. Запускаем тестовый пример который использует FindFirstChangeNotification и получаем уведомление об изменении на каждый вызов WriteFile!!! Как Вы понимаете это решение к условиям нашей задачи не подходит.
Зупускаем тестовый пример с использованием ReadDirectoryChangesW. Получаем два уведомления: первое на CreateFile второе на CloseHandle. Определить какое из них к чему относится по-моему не представляется возможным, так как оба раза мы получаем сообщение, что файл был модифицирован и всё. Можно конечно пофантазировать, что после вызова CreateFile его размер ещё равен 0, а на CloseHandle уже имеется реальный размер, но а что если файл уже существует и он не нулевого размера? Как тогда? (Ксати тут по этому поводу даже баг имеется(MSDN Q245214) и второе сообщение, то, что после CloseHandle, можно вообще умудриться не получить. У меня это пару раз получилось.)
Использование всех остальных параметров в ReadDirectoryChangesW тоже приводит ещё к худщим результатам. По крайней мере мне не удалось получить одно единственное сообщение после CloseHandle.
Как же решить проблему? Наиболее перспективным мне как раз представляется комбинация метода с использованием FindFirstChangeNotification с параметром FILE_NOTIFY_CHANGE_LAST_WRITE и методом предложенным Shaman_Naydak © (11.03.02 12:07). Дело в том, что FindFirstChangeNotification с параметром FILE_NOTIFY_CHANGE_LAST_WRITE для 98(полагаюсь на Вас) будет вызываться только по окончании процесса копирования, а для Win2000 2 раза: после SetEndOfFile и после CloseHandle. Но после первого раза, файл открыть мы просто не сможем, а второй раз будет тот который нам нужен.... Вообщем вот такие рассуждения... Честно говоря ковырятся в этом больше желания нет, работа стоит... за сим и прошу откланяться :)



Юрий Зотов   (2002-03-13 23:01) [42]

> Но после первого раза, файл открыть мы просто не сможем,

Чтобы открыть файл, нужно знать его имя. Но если известно имя копируемого файла, то проблем, IMHO, вообще нет. Просто надо использовать ReadDirectoryChangesW, а файл создать САМИМ и расшарить его на запись, причем сделать это ПЕРЕД установкой ловушки!!!

Идея в том, что тогда уведомление по CreateFile мы не получим (он ведь уже будет создан заранее!) и останется только уведомление по CloseHandle. Но это надо проверять.



Suntechnic   (2002-03-13 23:49) [43]

>Юрий Зотов © (13.03.02 23:01)
>...а файл создать САМИМ ...
Насколько я понял задачу она следующая: Представьте себе программу, которая отображает картинки в какой-либо папке. Надо при изменении состояния это папки(скажем кто-нибудь решил туда скопировать файл) отобразить только что появившуюся картинку. Т.е. мы сами ничего не создаём!!! Мы следим за изменениями!!! А проблема у автора в том, что если файл копируется долго(скажем из Инета), то он(автор) не может отловить момент, когда копирование файла закончено полностью и он может уже быть отображён(до этого момента мы просто получим ошибку пытаясь нарисовать картинку). Т.е. во всех вариантах(тех что перебробовал я лично) в лучшем случае приходят 2 сообщения: в момент создания файла(это не совсем так, но допустить можно) и в момент его закрытия. Но установить достоверное какое сообщение чему соответствует, как я вижу, не представляется возможным. Так что я не совсем понял как тут может помочь ReadDirectoryChangesW.



panov   (2002-03-14 07:52) [44]

Есть еще одна загвоздка, связанная с инетом.
Некоторые программы скачивания файлов с FTP могут многократно открывать и закрывать файл при выкачивании.
Вот в этом случае задача точно не может быть решена способами, описанными выше.

Хотя в голову пришел один метод.
1. Получаем уведомление методом FindFirst___ и.д.
2. Получаем имя файла и запоминаем.
3. Устанавливаем TimeOut, напр. 5 сек.
4. Если по истечении TimeOut не поступило вновь уведомление об изменении файла, считаем, что копирование закончилось, в противном случае переустанавливаем TimeOut.

Это общий набросок. Наверняка при реализации возникнут еще проблемы.




Страницы: 1 2 вся ветка
Форум: "Потрепаться";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2002.04.22;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.89 MB
Время: 0.045 c
14-70010          Nikolay               2002-03-15 12:11  2002.04.22  
Где можно почитать про итерацию?


3-69691           GenBr                 2002-03-28 14:07  2002.04.22  
midas


14-69976          False_Delirium        2002-03-12 10:07  2002.04.22  
Microsoft не перестаёт удивлять..:)...


4-70064           Geser_                2002-02-16 18:35  2002.04.22  
Как сделать screen-capture?


3-69716           Viktor Erko           2002-03-30 10:27  2002.04.22  
Потеря 1-4 коп. при суммировании чисел из базы даных