自做的文件复制函数,在复制大文件时进度条无法正常显示,像死机似的,有没有办法解决。 自做的文件复制函数(用API的FileCopy(...)),在复制大文件时进度条无法正常显示,像死机似的,有没有办法解决。100分。(能做出像Winows的文件复制的效果。) 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 用fileread和filewrite吧可以先取得文件的大小,然后按字节读和写。(不是单个字节的读)这样进度条比较好控制。可惜pascal的语法忘的差不多了,只能说这么多 别用FileCopy吧,自己读写文件,用I/O 函数,或者流都可以。 如果是普通文件(也可以是二进制),DELPHI里有很好用的函数,BlockRead, BlockWrite,详细的参数你可以看一下帮助,这两个可以帮助你读和写,这样根据文件大小,很容易可以控制进度表,速度很快的(可以每次读2048以上字节,以加快之) :-> ) 循环中加入Application.ProcessMessages;或放入子线程中处理 楼主在等代码否?要的话说一声。反正我不会写,正好看看。hoho...我up, up, up 多个文件用Application.ProcessMessages;是可以的,但我说的是只有一个文件的时候,并且这个文件很大,如100M时,如果文件很小当然没事啦 说不定Windows.CopyFileEx可以,但我也不会用,问问SDK/API的大牛们。 不用自己写吧,用一个API不行吗?WINSHELLAPI int WINAPI SHFileOperation( LPSHFILEOPSTRUCT lpFileOp );在Delphi给你一个例子吧:uses ShellAPI;procedure TForm1.Button1Click(Sender: TObject);var ShFile:TSHFILEOPSTRUCT;begin ShFile.Wnd:=Handle; ShFile.pFrom:='D:\Example'; ShFile.pTo:='P:\PJ'; ShFile.wFunc:=FO_COPY; SHFileOperation(ShFile);end; 我不要API的,我要的是自己编的 其实用SHFileOperation很好啊,连对话框都有的。CopyFile不也是API吗?一定要自己写的话,就用TFileStream或者TMemoryStream,比较方便。 顺便说一句,API里面好东西多的是。大部分时候,当然有特殊要求的情况例外,只要是它有的函数,都会比你能写出来的要好,至少是会更通用。有很多Delphi的函数不过就是简单的封装一下API而已。再说这些东西最后都是要着落到API上实现的,你又何必计较那么多? CopyFileEx(...)可以,它有一个回调 摩托~~~have a try:Function CopyProgressRoutine( TotalFileSize : Int64; TotalBytesTransferred : Int64; StreamSize : Int64; StreamBytesTransferred : Int64; dwStreamNumber : Cardinal; dwCallbackReason : DWord; hSourceFile : THandle; hDestinationFile : THandle; lpData : Pointer):integer;Begin form1.ProgressBar1.Max:=StreamSize; form1.ProgressBar1.Min :=0; form1.ProgressBar1.Position := StreamBytesTransferred; application.ProcessMessages ; Result := PROGRESS_CONTINUE;end;procedure TForm1.Button1Click(Sender: TObject);begin if copyfileex(pchar('d:\ttt.mp3'),pchar('d:\lll.mp3'),@copyprogressroutine,nil,0,COPY_FILE_FAIL_IF_EXISTS) then showmessage('ok');end; 楼主:没有FileCopy这个API啊!嗬嗬,只有CopyFile和CopyFileEx这两个API啊!CopyFileEx这个API中的回调函数是干嘛用的?这个回调函数就是提供Copy的百分比的啊!看到同志们这么多的议论我要昏倒了! to BlueTrees: CopyFileEx似乎只能在NT下用哦。 摩托的CopyFileEx的回调例子,没有问题的~~~~~ CopyFileEx的确只能在nt 2000下用~~~ function CreateFileStream(const filename: string; mode: Word): TFileStream;begin try Result := TFileStream.Create(filename, mode); except Result := nil; end;end;function MyCopyFile(const sfn, dfn: string): integer; // Copy file ; ret 0 for ok, 1 for open error, 2 for copy errorvar sfm: TFileStream; dfm: TFileStream; hDir: string; i: integer; wantsize: integer; errstr: string; rescode: integer; tempstr: string; PreTick: Int64; CurTick: Int64; TransKValid: Int64;begin // SyncForm.syncMeter.Position := 0; hDir := ExtractFileDir(dfn); if not DirectoryExists(hDir) then ForceDirectories(hDir); if FileExists(dfn) then FileSetAttr(dfn, faArchive); // because some file can't be modified; rescode := 0; dfm := CreateFileStream(dfn, fmCreate); sfm := CreateFileStream(sfn, fmOpenRead or fmShareDenyNone); PreTick := GetTickCount(); TransKValid := KILO16; wantsize := 1; try if (dfm = nil) then begin errstr := Faces[SYNLANBASE + 3] + dfn; rescode := 2; end else if (sfm = nil) then begin errstr := Faces[SYNLANBASE + 4] + sfn; rescode := 1; end else repeat CurTick := GetTickCount(); if CurTick > PreTick then begin Inc(TransKValid, CurrTask.MaxSpeed * (CurTick-PreTick)); PreTick := CurTick; end; if TransKValid < KILO16 then begin Application.ProcessMessages(); Continue; end; wantsize := KILO16; if wantsize > sfm.Size - sfm.Position then wantsize := sfm.Size - sfm.Position; if wantsize > 0 then begin if (SyncStatus = ssBreak) then begin errstr := Faces[SYNLANBASE + 5] + sfn; rescode := 4; Break; end; try i := dfm.CopyFrom(sfm, wantsize); if i <> wantsize then begin rescode := 3; Break; end; Dec(TransKValid, i); except errstr := Faces[SYNLANBASE + 6] + sfn; rescode := 3; Break; end; if i > 0 then begin tempstr := Faces[SYNLANBASE + 7]; SyncForm.syncMeter.Position := Int64(sfm.position) * 100 div sfm.Size; // 02252104 Inc(fcSizeNow, i); SyncForm.totMeter.Position := fcSizeNow * 100 div fcTotalSize; // 02252104 Replace(tempstr, '%1', Size2String(fcSizeNow)); Replace(tempstr, '%2', Size2String(fcTotalSize - fcSizeNow)); SyncForm.Label4.Caption := tempstr; end; end; Application.ProcessMessages(); until (wantsize = 0); finally if sfm <> nil then sfm.Free(); if dfm <> nil then dfm.Free(); if wantsize > 0 then // 未完成 begin if dfm <> nil then DeleteFile(dfn); // 删除未完成的目标文件 resForm.resMemo.Lines.Append(errstr); end; end; if rescode = 0 then // ok begin FileSetAge(dfn, FileAge(sfn)); FileSetAttr(dfn, FileGetAttr(sfn)); end; Result := rescode;end; (补充)以下变量用于限制复制速度 PreTick: Int64; CurTick: Int64; TransKValid: Int64 熟悉报表的请进 richedit的奇怪问题,bug还是我的程序错误!! 如何用ListView 显示数据库的数据? 并单击标题排序,而且单某个字段值大于10时候显示不同的颜色? 请问如何关闭窗口?MDIChild类型的。我用菜单打开,语句详见内。打开的窗口中,与关闭有关的语句也详见内。 Delphi7 的一个BUG. 怎样取得文件的日期时间信息? 实例化算不算继承? 最容易得的分数 select top 10 * from czbtem 为什么不行呢? Delphi报表分列问题 根据屏幕分辨率自动调整窗体位置和大小 Delphi低版本和高版本有何区别?
可以先取得文件的大小,然后按字节读和写。(不是单个字节的读)
这样进度条比较好控制。
可惜pascal的语法忘的差不多了,只能说这么多
自己读写文件,用I/O 函数,或者流都可以。
BlockRead, BlockWrite,详细的参数你可以看一下帮助,这两
个可以帮助你读和写,这样根据文件大小,很容易可以控制进度
表,速度很快的(可以每次读2048以上字节,以加快之)
:-> )
Application.ProcessMessages;或放入子线程中处理
我up, up, up
WINSHELLAPI int WINAPI SHFileOperation( LPSHFILEOPSTRUCT lpFileOp
);
在Delphi给你一个例子吧:
uses
ShellAPI;
procedure TForm1.Button1Click(Sender: TObject);
var
ShFile:TSHFILEOPSTRUCT;
begin
ShFile.Wnd:=Handle;
ShFile.pFrom:='D:\Example';
ShFile.pTo:='P:\PJ';
ShFile.wFunc:=FO_COPY;
SHFileOperation(ShFile);
end;
大部分时候,当然有特殊要求的情况例外,只要是它有的函数,都会比你能写出来的要好,至少是会更通用。有很多Delphi的函数不过就是简单的封装一下API而已。再说这些东西最后都是要着落到API上实现的,你又何必计较那么多?
TotalFileSize : Int64;
TotalBytesTransferred : Int64;
StreamSize : Int64;
StreamBytesTransferred : Int64;
dwStreamNumber : Cardinal;
dwCallbackReason : DWord;
hSourceFile : THandle;
hDestinationFile : THandle;
lpData : Pointer):integer;Begin
form1.ProgressBar1.Max:=StreamSize;
form1.ProgressBar1.Min :=0;
form1.ProgressBar1.Position := StreamBytesTransferred;
application.ProcessMessages ;
Result := PROGRESS_CONTINUE;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if copyfileex(pchar('d:\ttt.mp3'),pchar('d:\lll.mp3'),@copyprogressroutine,nil,0,COPY_FILE_FAIL_IF_EXISTS) then showmessage('ok');
end;
没有FileCopy这个API啊!嗬嗬,
只有CopyFile和CopyFileEx这两个API啊!
CopyFileEx这个API中的回调函数是干嘛用的?这个回调函数就是提供Copy的百分比的啊!
看到同志们这么多的议论我要昏倒了!
CopyFileEx似乎只能在NT下用哦。
begin
try
Result := TFileStream.Create(filename, mode);
except
Result := nil;
end;
end;function MyCopyFile(const sfn, dfn: string): integer; // Copy file ; ret 0 for ok, 1 for open error, 2 for copy error
var
sfm: TFileStream;
dfm: TFileStream;
hDir: string;
i: integer;
wantsize: integer;
errstr: string;
rescode: integer;
tempstr: string;
PreTick: Int64;
CurTick: Int64;
TransKValid: Int64;
begin //
SyncForm.syncMeter.Position := 0; hDir := ExtractFileDir(dfn);
if not DirectoryExists(hDir) then
ForceDirectories(hDir);
if FileExists(dfn) then
FileSetAttr(dfn, faArchive); // because some file can't be modified; rescode := 0; dfm := CreateFileStream(dfn, fmCreate);
sfm := CreateFileStream(sfn, fmOpenRead or fmShareDenyNone);
PreTick := GetTickCount();
TransKValid := KILO16;
wantsize := 1;
try
if (dfm = nil) then
begin
errstr := Faces[SYNLANBASE + 3] + dfn;
rescode := 2;
end
else if (sfm = nil) then
begin
errstr := Faces[SYNLANBASE + 4] + sfn;
rescode := 1;
end
else
repeat
CurTick := GetTickCount();
if CurTick > PreTick then
begin
Inc(TransKValid, CurrTask.MaxSpeed * (CurTick-PreTick));
PreTick := CurTick;
end;
if TransKValid < KILO16 then
begin
Application.ProcessMessages();
Continue;
end;
wantsize := KILO16;
if wantsize > sfm.Size - sfm.Position then
wantsize := sfm.Size - sfm.Position;
if wantsize > 0 then
begin
if (SyncStatus = ssBreak) then
begin
errstr := Faces[SYNLANBASE + 5] + sfn;
rescode := 4;
Break;
end;
try
i := dfm.CopyFrom(sfm, wantsize);
if i <> wantsize then
begin
rescode := 3;
Break;
end;
Dec(TransKValid, i);
except
errstr := Faces[SYNLANBASE + 6] + sfn;
rescode := 3;
Break;
end;
if i > 0 then
begin
tempstr := Faces[SYNLANBASE + 7];
SyncForm.syncMeter.Position := Int64(sfm.position) * 100 div sfm.Size; // 02252104
Inc(fcSizeNow, i);
SyncForm.totMeter.Position := fcSizeNow * 100 div fcTotalSize; // 02252104
Replace(tempstr, '%1', Size2String(fcSizeNow));
Replace(tempstr, '%2', Size2String(fcTotalSize - fcSizeNow));
SyncForm.Label4.Caption := tempstr;
end;
end;
Application.ProcessMessages();
until (wantsize = 0);
finally
if sfm <> nil then
sfm.Free();
if dfm <> nil then
dfm.Free();
if wantsize > 0 then // 未完成
begin
if dfm <> nil then
DeleteFile(dfn); // 删除未完成的目标文件
resForm.resMemo.Lines.Append(errstr);
end;
end;
if rescode = 0 then // ok
begin
FileSetAge(dfn, FileAge(sfn));
FileSetAttr(dfn, FileGetAttr(sfn));
end;
Result := rescode;
end;
PreTick: Int64;
CurTick: Int64;
TransKValid: Int64