Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.15.214.155] |
|
Сообщ.
#1
,
|
|
|
Я хочу откопировать папку. Для этого я использую копироание одного файла с помощью потока:
http://www.sources.ru/delphi/files/copy_fi...in_thread.shtml 1. Я создаю список файлов директории. 2. По списку копирую каждый файл. Но после того, как программа откопировала ~2000 файлов, она вылетает с ошибкой. Что делать? |
Сообщ.
#2
,
|
|
|
Цитата C какой ошибкой? И где создаещ список файлов? Heretic2, 28.06.04, 16:56 она вылетает с ошибкой |
Сообщ.
#3
,
|
|
|
Покеж код, кстати зачем 2 темы?
|
Сообщ.
#4
,
|
|
|
uses ShellApi; function WorkFile(metod: Cardinal; FromFile,ToDir: string; const WndShow: Boolean = False; const Flags: Word = FOF_ALLOWUNDO or FOF_NOCONFIRMATION ): boolean; // Действия над файлами var FileOp: TSHFileOpStruct; // Source: string; begin FillChar(FileOp, SizeOf(FileOp), #0); With FileOp do Begin if WndShow then Wnd:= GetActiveWindow; wFunc:= metod; FromFile:= FromFile + #0; // 07.09.03 pTo:= pTo + #0; // 29.06.04 pFrom:= PChar(FromFile); pTo:= PChar(ToDir); fFlags:= Flags; fAnyOperationsAborted:= False; hNameMappings:= nil; lpszProgressTitle:= nil; end; result:= ShFileOperation(FileOp) = 0; end; // ----------------------------------------------------------------- function acCopyFile(FromFile,ToDir: string; const WndShow: Boolean = False; const Flags: Word = FOF_ALLOWUNDO or FOF_NOCONFIRMATION ): boolean; // Копирование файла begin result:= WorkFile(FO_COPY, FromFile, ToDir, WndShow, Flags); end; // ----------------------------------------------------------------- function acMoveFile(FromFile,ToDir: string; const WndShow: Boolean = False; const Flags: Word = FOF_ALLOWUNDO or FOF_NOCONFIRMATION ): boolean; // Перемещение файла begin result:= WorkFile(FO_MOVE, FromFile, ToDir, WndShow, Flags); end; // ----------------------------------------------------------------- function acDeleteFile(aFile: string; const WndShow: Boolean = False; const Flags: Word = FOF_ALLOWUNDO or FOF_NOCONFIRMATION ): boolean; // Удаление файла begin result:= WorkFile(FO_DELETE, aFile, '', WndShow, Flags); end; Пример использования procedure TForm1.Button1Click(Sender: TObject); begin acCopyFile('e:\Prog\Delphi_Components\ZipTV_v4_for_Delphi6\*.*', 'E:\Temp\', False) end; |
Сообщ.
#5
,
|
|
|
Alex-Co,
В WorkFile надо добавить еще: ToDir := ToDir + #0; pTo:= PChar(ToDir); так как на параметр ToDir распространяется тоже правило что и на FromFile. Вот выдержка из MSDN: Цитата pTo Address of a buffer to contain the name of the destination file or directory. This parameter must be set to NULL if it is not used. Like pFrom, the pTo member is also a double-NULL terminated string and is handled in much the same way. However, pTo must meet the following specifications: |
Сообщ.
#6
,
|
|
|
Добавлю, спасибо
|
Сообщ.
#7
,
|
|
|
1. Как решить мою проблему!(код вскоре выложу)
2. В приведённом выше примере можно ли узнать на сколько процентов откопирован файл? |
Сообщ.
#8
,
|
|
|
Надо юзать вот это lpszProgressTitle
|
Сообщ.
#9
,
|
|
|
и как "вот это" юзать
|
Сообщ.
#10
,
|
|
|
Всё-таки у меня осталось парочка вопросов.
1. Почему прога вылетает с ошибкой "Thread creation error: Недостаточно памяти для обработки команды", причём прога вылетает после копирования ~2000 файлов(любого размера)? 2. Есть ли какой нибудь другой метод копирования файла (без вызова виндового окна) , при этом методе (желательно) можно узнать на скольлко процентов файл откопирован? 3. Если нет других вариантов, то подскажите, как сделать так, чтобы Windows'овское окно не задавало вопросов, типа "Файл уже существует: переписать поверх"? Вот код проги!!! //----------------------------------------------- //Copy files //----------------------------------------------- constructor TCopyFile.Create(Src, Dest : String); begin IName := Src; OName := Dest; Percent := 0; Start := Now; FreeOnTerminate := True; inherited Create(True); end; procedure TCopyFile.Execute; var fi,fo : TFileStream; dod,did : Integer; cnt,max : Integer; begin Start := Now; try fo := TFileStream.Create(OName, fmOpenReadWrite); fo.Position:=fo.size; except fo := TFileStream.Create(OName, fmCreate); end; try fi := TFileStream.Create(IName, fmOpenRead); try cnt:= fo.Position; fi.Position := cnt; max := fi.Size; ToDo := Max-cnt; Done := 0; Repeat dod := MB1; if cnt+dod>max then dod := max-cnt; if dod>0 then did := fo.CopyFrom(fi, dod); cnt:=cnt+did; if max<>0 then Percent := Round(Cnt/Max*100) else Percent:=100; cursize:=cnt; form3.Gauge1.Progress:=Percent; form3.label5.caption:=inttostr(curprog); form3.label6.caption:=inttostr(cursize); form3.label7.caption:=inttostr(dirbytes); if DirBytes<>0 then form3.Gauge2.Progress:=Round((curprog+cursize)/DirBytes*100); Done := Done+did; ToDo := Max; until (dod=0) or (Terminated); finally fi.free; end; finally fo.free; end; end; procedure CopyDir(FromDir, ToDir: string); var i : integer; abc : Tcopyfile; f: file of byte; begin form3.gauge1.Progress:=0; form3.gauge2.Progress:=0; cursize:=0; curprog:=0; createdir(ToDir); for i:=0 to stnum-1 do begin if FileExists(FromDir+form3.Memo1.Lines.Strings[i]) then begin assignfile(f, ToDir+form3.Memo1.Lines.Strings[i]); rewrite(f); closefile(f); form3.Gauge1.Progress:=0; abc:=Tcopyfile.Create(FromDir+form3.Memo1.Lines.Strings[i], ToDir+form3.Memo1.Lines.Strings[i]); abc.Execute; application.ProcessMessages; curprog:=curprog+cursize; form3.Caption:=inttostr(i);//form3.Memo1.Lines.Strings[i]; end else begin createdir(ToDir+form3.Memo1.Lines.Strings[i]); end; end; end; function DirList(Dir, s:string):integer; var SearchRec : TSearchRec; Separator : string; begin if Copy(Dir,Length(Dir),1)='\' then Separator := '' else Separator := '\'; if FindFirst(Dir+Separator+'*.*',faAnyFile,SearchRec) = 0 then begin if FileExists(Dir+Separator+SearchRec.Name) then begin DirBytes := DirBytes + SearchRec.Size; stnum:=stnum+1; form3.Memo1.Lines.Add(s+SearchRec.Name); end else if DirectoryExists(Dir+Separator+SearchRec.Name) then begin if (SearchRec.Name<>'.') and (SearchRec.Name<>'..') then begin stnum:=stnum+1; form3.Memo1.Lines.Add(s+SearchRec.Name); DirSize(Dir+Separator+SearchRec.Name, s+SearchRec.Name+'\'); end; end; while FindNext(SearchRec) = 0 do begin if FileExists(Dir+Separator+SearchRec.Name) then begin DirBytes := DirBytes + SearchRec.Size; stnum:=stnum+1; form3.Memo1.Lines.Add(s+SearchRec.Name); end else if DirectoryExists(Dir+Separator+SearchRec.Name) then begin if (SearchRec.Name<>'.') and (SearchRec.Name<>'..') then begin stnum:=stnum+1; form3.Memo1.Lines.Add(s+SearchRec.Name); DirSize(Dir+Separator+SearchRec.Name,s+SearchRec.Name+'\'); end; end; end; end; FindClose(SearchRec); end; procedure TForm3.Button1Click(Sender: TObject); var fs, sp: string; begin fs:='d:\cs\'; sp:='D:\cs2\'; dirlist(fs,''); copydir(fs,sp); end; |
Сообщ.
#11
,
|
|
|
Цитата Heretic2, 31.07.04, 23:48 (без вызова виндового окна) Можно, усли указать флаг SH_SILENT. Цитата Heretic2, 31.07.04, 23:48 "Thread creation error: Недостаточно памяти для обработки команды" Попробуй тоже сделать через WinExplorer, если он вылетает, значит придется ручками через TFileStream |
Сообщ.
#12
,
|
|
|
Цитата Heretic2, 31.07.04, 23:48 1. Почему прога вылетает с ошибкой "Thread creation error: Недостаточно памяти для обработки команды", причём прога вылетает после копирования ~2000 файлов(любого размера)? Да потому, что ты неправильно используеш потоки. То как у тебя написано, это не правильно. У тебя нет никакой многопоточности . Не надо самому вызываеть метод Execute потока! a) Вместо вызова Execute, надо вызвать Resume - лишь тогда Execute будет запущена в отдельном потоке. И лишь тогда, по завершению Execute, поток бужет завершен, и объект потока будет разрушен. У тебя этого не происходит, поэтому наверное и памяти не хватает. b) При правильном запуске потока (см. пункт a), внутри Execute НЕЛЬЗЯ напрямую обращаться к методам и свойствам объектов VCL (Gauge1, Label5, и пр.). Делать это нужно только через Synchronize. В общем, почитай-ка сначала теорию, а именно, о том как писать многопоточные приложения на Delphi. Цитата Heretic2, 31.07.04, 23:48 2. Есть ли какой нибудь другой метод копирования файла (без вызова виндового окна) , при этом методе (желательно) можно узнать на скольлко процентов файл откопирован? 3. Если нет других вариантов, то подскажите, как сделать так, чтобы Windows'овское окно не задавало вопросов, типа "Файл уже существует: переписать поверх"? Тебе же писали ShFileOperation. А по поводу "окон" и "вопросов", то почитай описание функции ShFileOperation, а именно, описание поля fFlags структуры SHFILEOPSTRUCT, передаваемой ей в качестве параметра. |
Сообщ.
#13
,
|
|
|
И в дополнение - копирование файлов в потоках приводить к резкому замедлению работы, не считая того, что надо быть на ВЫ с потоками.
Напомню еще раз - для всех операций с файлами использовать ShFileOperation, кроме особых случаев. |
Сообщ.
#14
,
|
|
|
Цитата Anatoly Podgoretsky, 1.08.04, 12:14 надо быть на ВЫ с потоками. Наверное, лучше на ТЫ Цитата Anatoly Podgoretsky, 1.08.04, 12:14 копирование файлов в потоках приводить к резкому замедлению работы Думаю что да. Головки винчестера только и будут делать что носиться взад-вперед. |