全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1792
推到 Plurk!
推到 Facebook!

多线程断点续传的问题

答題得分者是:Ktop_Robot
lonmener
一般會員


發表:16
回覆:32
積分:9
註冊:2005-08-20

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-09-05 23:20:39 IP:60.212.xxx.xxx 未訂閱
刚学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.
系統時間:2024-05-10 13:41:31
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!