多线程断点续传的问题 |
答題得分者是:Ktop_Robot
|
lonmener
一般會員 發表:16 回覆:32 積分:9 註冊:2005-08-20 發送簡訊給我 |
刚学DELPHI,编写一下多线程断点续传的程序
现在代码中感觉有两个问题,
一、记录文件操作的问题
原码中的while do的方法是否可行?是否有更好的?在网上看到关于多线程的“临界区”,在这里是否适用?如果适用的话应该怎么改?
二、保存到磁盘上的文件的问题
文件下载时先创建了大小与远程文件大小一样的文件,但我在使用TFileStream保存文件时为什么保存一个块后磁盘上的文件自动变成块的大小?是否有其它方法直接修改创建时的文件的大小不变? 附多线程原码
unit ThreadTest; interface uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Dialogs,StdCtrls,IdHTTP; type
Tmytest = class(TThread)
private
{ Private declarations }
// procedure MyDown;
protected
procedure Execute; override;
procedure HttpDownLoad(aURL, aFile: string); end; var
aURL,aFile:string; //分别为下载网址、保存文件名
logd:TStringList; //创建记录文件用
Slock:boolean; //用于记录文件状态用
icount:integer; //用于线程计数 implementation uses Unit1; { Tmytest } function CreateSemget(FileNameS:string;FileSizeS,SemgetVaule:int64):boolean; stdcall;
var //创建记录文件//SemgetVaule为分隔块的大小以K表示
i:integer;
n:Real;
begin //trunc舍入方法
//round四舍五入
SemgetVaule:=SemgetVaule*1024; //转换成k
FileNameS:=FileNameS '.nv'; //记录文件加扩展名 if FileSizeS=0 then
begin
Result:=false; //如果得到文件大小为0时则函数返回-1
end else
begin while Slock=true do sleep(10); //当记录文件正在操作中休眠0.01秒 Slock:=true;
logd:=TStringList.Create;
logd.Clear;
logd.SaveToFile(FileNameS);
logd.LoadFromFile(FileNameS); n:= FileSizeS/SemgetVaule;
logd.Add(IntToStr(FileSizeS)); if FileSizeS > SemgetVaule then
begin
for i:=1 to trunc(n) do
logd.Add(IntToStr(SemgetVaule*i) '/0');
if FileSizeS-trunc(n)*SemgetVaule > 0 then
begin
logd.Add(IntToStr(FileSizeS) '/0');
end;
end else
begin
logd.Add(IntToStr(FileSizeS) '/0');
end;
logd.SaveToFile(FileNameS);
Result:=true; //创建成功,返回0
logd.Free;
Slock:=false; //锁定状态关闭
end;
end; function WriteSemget(FileNameS:string;IndexS,StatuS:int64):boolean;stdcall;
var //改写记录文件中块的值
s:string;
i:integer;
begin
FileNameS:=FileNameS '.nv';
if not FileExists(FileNameS) then
begin
Result:=false;
end else
begin
while Slock=true do sleep(10); //当记录文件正在操作中休眠0.01秒
logd:=TStringList.Create;
logd.LoadFromFile(FileNameS);
Slock:=true;
try
s:=logd.Strings[IndexS];
i:=Pos('/',s);
Delete(s,i, 2);
logd.Strings[IndexS]:=s '/' inttostr(StatuS);
logd.SaveToFile(FileNameS);
Result:=true;
logd.Free;
Slock:=false;
except
Result:=false;
logd.Free;
Slock:=false;
end;
end;
end; function FindSTIndex(FileNameS:string;zeroStatu:integer): integer; stdcall;
var //查找记录文件中的序号(第几行)
s:string;
i:integer;
zeroindex:integer;
begin
FileNameS:=FileNameS '.nv'; if not FileExists(FileNameS) then
begin
Result:=-1;
end else
begin
while Slock=true do sleep(10); //当记录文件正在操作中休眠0.01秒
Slock:=true;
logd:=TStringList.Create;
logd.LoadFromFile(FileNameS);
for zeroindex:=1 to logd.Count do if zeroindex < logd.Count then
begin
s:=logd.Strings[ZeroIndex];
i:=Pos('/',s);
Delete(s,1, i);
if strtoint(s)= zeroStatu then
begin
Result:=ZeroIndex;
logd.Free;
Slock:=false;
break;
end
end else
begin
Result:=-1;
logd.Free;
Slock:=false;
end;
end;
end; function ReadSTValue(FileNameS:string;IndexS:integer): int64; stdcall;
var //读取记录文件中块的值
i:integer;
s:string;
begin //trunc舍入方法; round四舍五入
FileNameS:=FileNameS '.nv'; if FileExists(FileNameS) then
begin
if IndexS >0 then
begin
while Slock=true do sleep(10); //当记录文件正在操作中休眠0.01秒
Slock:=true;
logd:=TStringList.Create;
logd.LoadFromFile(FileNameS);
s:=logd.Strings[IndexS];
i:=Pos('/',s);
Delete(s,i,2);
Result:=StrToInt(s);
logd.Free;
Slock:=false;
end else
begin
Result:=-1;
logd.Free;
Slock:=false;
end;
end else
begin
Result:=-1;
logd.Free;
Slock:=false;
end;
end; function ReadSTStatu(FileNameS:string;ZeroIndex:integer): integer; stdcall;
var //读取记录文件中块的状态
i:integer;
s:string;
begin //trunc舍入方法; round四舍五入
FileNameS:=FileNameS '.nv'; if not FileExists(FileNameS) then
begin
Result:=-1; //如果记录文件不存在则返回-1
end else
begin repeat
sleep(10);
until Slock=false;
Slock:=true;
logd:=TStringList.Create;
logd.LoadFromFile(FileNameS);
try
s:=logd.Strings[ZeroIndex];
i:=Pos('/',s);
Delete(s,1, i);
Result:=StrToInt(s);
logd.Free;
Slock:=false;
except
Result:=-1;
logd.Free;
Slock:=false;
end;
end;
end;
function FileCreateSize(aFileName:string;aFileSize:int64):int64;stdcall;
//创建指定大小文件;成功返回文件大小;失败返回-1;
//FileCreateSize('d:\1.txt',10240);//在D盘上创建一个10240字节的1.txt文件
var
FC:HFile;
begin if not FileExists(aFileName) then
begin
FC:=FileCreate(aFileName,fmOpenWrite);
try
SetFilePointer(FC, Int64Rec(aFileSize).Lo, @Int64Rec(aFileSize).Hi, FILE_BEGIN);
SetEndOfFile(FC);
finally
Result:=aFileSize;
FileClose(FC);
end;
end else //文件存在,则返回-1
begin
Result:=-1;
Exit;
end;
end; procedure Tmytest.HttpDownLoad(aURL, aFile: string);
var
FS: TFileStream;
Myidhttp:TIdHTTP;
Fsize:Int64; //创建文件时需要
indexs:integer;
begin //Http方式下载 if not FileExists(aFile) then
begin
Myidhttp:=TIdHTTP.Create(nil); //动态创建IdHTTP控件
Myidhttp.Head(aURL);
Fsize:=Myidhttp.Response.ContentLength; //取得http服务器上文件大小
Myidhttp.Free;
FileCreateSize(aFile,Fsize); //创建文件
CreateSemget(aFile,Fsize,256); //创建记录文件
end;
sleep(1000);
indexs:=FindSTIndex(aFile,0);
if indexs < 1 then
begin
exit;
end;
if indexs=1 then
begin
WriteSemget(aFile,indexs,1);
FS:= TFileStream.Create(aFile, fmOpenWrite or fmShareDenyRead);
Myidhttp:=TIdHTTP.Create(nil);
Myidhttp.Request.ContentRangeStart := 0;
FS.Position := 0; //移动到启点下载
Myidhttp.Request.ContentRangeEnd:= ReadSTValue(aFile,indexs);
try
Myidhttp.Get(aURL, FS); //开始下载
WriteSemget(aFile,indexs,2);
finally
FS.Free;
Myidhttp.Free;
end;
end;
if indexs-1>0 then
begin
WriteSemget(aFile,indexs,1);
FS:= TFileStream.Create(aFile, fmOpenWrite or fmShareDenyRead);
Myidhttp:=TIdHTTP.Create(nil);
Myidhttp.Request.ContentRangeStart := ReadSTValue(aFile,indexs-1);
FS.Position := ReadSTValue(aFile,indexs-1); //移动到启点下载
Myidhttp.Request.ContentRangeEnd:= ReadSTValue(aFile,indexs);
try
Myidhttp.Get(aURL, FS); //开始下载
WriteSemget(aFile,Indexs,2);
finally
FS.Free;
Myidhttp.Free;
end;
end; end; procedure Tmytest.Execute;
begin
HttpDownLoad(aURL,aFile);
end;
end.
|
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |