-
var hFile : THandle; Tmp : LPDWORD; INRT : Int64;
hFile := CreateFile (PChar(FileName), FILE_ATTRIBUTE_READONLY, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if hFile = INVALID_HANDLE_VALUE then Exit; INRT := GetFileSize (hFile, @Tmp); StrError := PChar(SysErrorMessage(GetLastError)); StrError = 'Параметр задан неверно' Не подскажите в чем дело, что за параметр? От себя добавлю, что FileName является ВЗУ. Открываю я этот файл(ВЗУ) для редактирования filesystem. Конечно можно использовать цикл записи по n(512) байт, но это уморительно долго. И сразу второй вопрос. Произвожу запись файла ReadFile(FhDrive,GLArrayByte[0],SizeFile,br,nil) (с одной стороны здорово разом файл размером SizeFile байт) но возникает следущая задачка файл необходимо записывать в разные места диска (ВЗУ файловая система QNX4 - кто знает тот плавал) При записи файла размером 200м возникает не ловкая пауза перед пользователем. Опять же поблочная запись, по блокам(512) позволяет пользователю определить время на перекур по прогрессу, не подскажите как определить прогресс состояния записи в в случае быстрой(не поблочной) записи ReadFile(FhDrive,GLArrayByte[0],SizeFile,br,nil)
-
GetFileSize .. Parameters
hFile
Specifies an open handle of the file whose size is being returned. The handle must have been created with either GENERIC_READ or GENERIC_WRITE access to the file.
> не ловкая пауза перед пользователем
Изловчись выполнять подобного рода операции в дополнительном кодовом потоке, тогда будет "ловкая пауза"
-
> дополнительном кодовом потоке
что в этом потоке крутить? Я думал может есть какие ловушки, ну на крайний запустить процесс секунды на 3 глянуть сколько и за что.
> GENERIC_READ or GENERIC_WRITE
заменил не помогло.
-
> что в этом потоке крутить?
Крути все операции, за которые тебе стыдно перед юзером)
> думал может есть какие ловушки
Можно и без ловушек и без доп.потоков. На то существует overlapped-ввод/вывод, а также порты завершения
см. все что касается OVERLAPPED-режима Create/Read/WriteFile
-
OlegNik (25.12.08 12:12) но возникает следущая задачка файл необходимо записывать в разные места диска MMF не подойдет? мапить только то что нужно а не весь файл
-
OlegNik (25.12.08 12:12) но возникает следущая задачка файл необходимо записывать в разные места диска MMF не подойдет? мапить только то что нужно а не весь файл
-
пытался через OVERLAPPED но
hFile := CreateFile (PChar(FileName), FILE_ATTRIBUTE_READONLY, FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE, nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
Да вроде можно посмотреть через WaitForSingleObjectEx сколько записал к определенной секунде, но увы не могу понять почему перестал работать SetFilePointer или аналог _llSeek, может знает кто?
-
> перестал работать > SetFilePointer
Неужели вот прямо так и говорит "Я перестал работать" ?
-
> Неужели вот прямо так и говорит "Я перестал работать" ?
Да нет, не прямо так. Говорит 'Параметр задан неверно'. Функция возвращает High(DWord); SetFilePointer(hFile, tmpLo , @tmpHi, FILE_BEGIN);
-
> OlegNik (26.12.08 16:58) [6]
> увы не могу понять почему перестал работать > SetFilePointer или аналог _llSeek, может знает кто?
The file pointer identified by the value of the hFile parameter is not used for overlapped read and write operations. To specify the offset for overlapped operations, use the Offset and OffsetHigh members of the OVERLAPPED structure.
-- Regards, LVT.
-
> To specify the offset for overlapped > operations, use the Offset and OffsetHigh members > of the OVERLAPPED structure.
А не в курсе как заполнять OVERLAPPED?
-
> OlegNik (27.12.08 12:39) [10]
> А не в курсе как заполнять OVERLAPPED?
Ну, каждое поле и заполнять. А чего, msdn.microsoft.com не работает?
-- Regards, LVT.
-
Виноват не то спросил.
FillChar(Overlap,SizeOf(TOVERLAPPED),0); Overlap.hEvent := CreateEvent(0,True,False,0); Overlap.offSet := 512 * 9000; res := WriteFileEx();
while WaitForSingleObjectEx(Overlap.hEvent,1000,True) = WAIT_TIMEOUT do begin Application.ProcessMessages; end;
В части записи с нужной мне позиции все нормально запись прозводится в поном объеме, но по истечению времени t=1с, я не вижу фактического изменения числа записанных байт в Overlap, что не так. Или возможно путь указаный т. Сергей М. ложный.
-
см. GetOverlappedResult
-
> см. GetOverlappedResult
while WaitForSingleObjectEx(Overlap.hEvent,1000,True) = WAIT_TIMEOUT do begin GetOverlappedResult(hFile,Overlap,realW,False); Form1.Caption := IntToStr(realW); {при GetOverlappedResult(hFile,Overlap,realW,True); уходит ПО в "себя"} Application.ProcessMessages; end;
-
ну и понятно realW = 0.
-
while True do begin case WaitForSingleObjectEx(Overlap.hEvent,1000,True) of WAIT_TIMEOUT: //прошла секунда, но сигнал окончания ovl-операции не обнаружен begin Application.ProcessMessages; continue; //ждем дальше end; WAIT_OBJECT_0: // обнаружен сигнал завершения ovl-операции begin Win32Check(GetOverlappedResult(hFile,Overlap,realW,False) <> 0); Form1.Caption := IntToStr(realW); break; end; end; end;
-
Это понятно и здорово. Но мне хотелось бы узнать сколько байт записано по истечению секунды на WAIT_TIMEOUT: Win32Check(GetOverlappedResult(hFile,Overlap,realW,False) <> False); выдает ошибку "наложенное событие ввода/вывода не находится в сигнальном состоянии" короче code : 996. Как быть?
-
Никак.
WAIT_TIMEOUT означает, что по истечении указанного периода операция не завершилась. Запрашивать результаты незавершенной операции бессмысленно, о чем собссно и говорит отказ с кодом 996.
-
Ну а теперь самое главное. Я против того, чтобы делать ради того чтобы делать. Мой вопрос заключался в следующем: Можно ли при записи данных большого объема что называется "за раз" узнать сколько байт записано к определенному моменту времени, хотябы для вывода вывода этих данных в прогресс. А что был за совет с
> см. все что касается OVERLAPPED-режима Create/Read/WriteFile
Блеск знаниями или что? Но всеравно спасибо за "науку".
-
> При записи файла размером 200м возникает не ловкая пауза > перед пользователем
Чтобы она была "ловкая", нужно как минимум оживить UI, согласен ? Сделать это можно любым из двух способов - вынос операции (блокирующей или неблокирующей - неважно) в доп.процесс/доп.поток или запуск операции в UI-потоке в асинхронном неблокирующем режиме. Последнее реализуется как раз с использованием overlapped i/o механизма.
Прогресс-нотификация же - это совсем другая (и весьма нетривиальная по ряду важных причин) задача, напрямую не связанная с i/o-режимами.
Win32API предлагает единственную функцию, предоставляющую интерфейс прогресс-нотификации - CopyFileEx. Но если посмотреть на ее "внутренности", то там можно увидеть то самое блочное чтение/запись, от которых ты пытаешься уйти. И уйти по непонятным мне пока причинам, ибо ничто не мешает использовать блоки более крупного размера, нежели 0,5К
-
Реализовал следующим способом 1. Убедился что файл действительно большой 2. Запускаю пробную запись(чтение) отследил время 3. Ну а потом действительно твоя помощь в цикл к варианту WAIT_TIMEOUT добавил расчет положения прогресса (формулу определения дальности еще не отменили) В случае с WAIT_OBJECT_0 позиция прогресса = 100 (Ух ты высокое методическое мастерство позволило завершить процесс записи/чтения несколько быстрее чем ожидалось). Все спасибо, вопрос закрываю.
-
Фигня это, а не прогресс. В топку его. Любое изменение в общесистемных условиях выполнения операции приведет к обрушению этого карточного домика по самый фундамент.
Уж лучше честную липу показать юзеру - анимашку какую-нить.. Главное чтобы не скучал)
-
> в цикл к варианту WAIT_TIMEOUT добавил расчет положения
Это называется "К соседу за спичками через Северный полюс". По сути мощь и возможности wait-функции сводятся до использования в качестве банального таймера.
|