Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2002.04.22;
Скачать: [xml.tar.bz2];

Вниз

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

 
Юрий Зотов   (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 вся ветка

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

Наверх





Память: 0.54 MB
Время: 0.011 c
14-69984
Кулюкин Олег
2002-03-12 08:57
2002.04.22
DBAware компоненты - за и против


6-69958
ctapik-net
2002-01-18 06:52
2002.04.22
Как зная IP адрес компа в сети получить его имя?


1-69906
DeMoN-777
2002-04-09 14:09
2002.04.22
Поиск в ListBox


14-70002
murdoc
2002-03-15 12:27
2002.04.22
Улетный сайт - ADMISHA.H1.RU


1-69930
Veselov
2002-04-08 20:10
2002.04.22
PDF, или как получить доступ к тексту внутри него ?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский