多线程 实现大文件的复制(100分)

S

shbjkl

Unregistered / Unconfirmed
GUEST, unregistred user!
我想将一个大文件分成多块来复制每一块用一个线程
思路:线程同时将源文件中取出一块,写到目标文件对应的一块
问题:怎样实现块复制(就是块的起末位置确定,及方法)
 
不建议用多线程复制文件,这个时候是文件I/O消耗时间,根本无法利用多线程的优势。
 
就是类似flashget的功能,它也不是将一个文件分成多块在合并的吗
 
你自己去复制一个600MB的文件,没有的话,找张VCD,
看看CPU 100%,还能干什么?
 
他是从网络上读数据,在读之前,他就建立了一个和当前下载文件一样大的文件,
在这个时候一般网络下文件的速度远远慢于写文件的速度,所以这个时候磁盘I/O
就不是问题,所以就可以用他的分块写文件,而你复制文件,多线程复制文件主要
都在ReadBuffer,WriteBuffer什么的,都是把文件读入内存,然后把内存里的数据
写回文件,这个是无法很难利用多线程的优势,而且如果你用了多线程以后,磁盘
读写每次无规律的移动,不是单线程的规律顺序移动,寻道消耗的时间可能更多。
 
同意张无机
 
谢谢各位的参与!!!
我只是想学习一下这个过程效率问题就不考虑了。
 
张教主分析得很好,学习!
 
同志们,给我实在一点的吧。
 
看看这个:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2016628
 
不同意张无际的观点。尽管io操作无法利用多线程的优势,但是在某些特定条件下多线程读写文件还是有很大的优势的,比如读写之间要进行很大量而耗费时间的操作。
 
to Another_eYes:
楼主是文件复制呀,不是你说的特定条件,我在开始的时候也说清楚了,根据写硬盘的时间
和你处理数据的时间的关系来对比判断是否才用多线程操作呀,[:D]
 
我觉得楼主的描述不详细。
我做过600M的文件用线程复制,当时是在做压缩。
1:分几块要明确(如10块)
2:几个线程要明确(如5个)
3:每个线程采用内存流取数据(加载流,移动指针到属于他的块,READBUFFER)procedure readbuffer
var vv:string;buf:tmemorystream;n,v:integer;
begin
buf:=tmemorystream.create;
buf.loadfile('d:/aa.dat');
setlength(vv,buf.size);
buf.readbuffer(vv[1],buf.siza);
n:=块数; //建议采用2块
v:=块的大小; //动态决定
end;
// 好多变量采用全局。
t1.execute;
//比如他只做第一块和第五块
var v1,v5:string;
begin
v1:= copy(vv,1,v);
v5:=copy(vv,4*n+1,v);
....(放到相应的地方)
end;
 
unit Unit2;
interface
uses
Classes,activex,SysUtils;
type
tfilecopy = class(TThread)
private
fs,fd:integer;
fsname,fdname:Tfilestream;
{ Private declarations }
protected
procedure Execute;
override;
public
constructor create(sname,dname:Tfilestream;s,d:integer);
end;

implementation
const
buffersize=1024*1024;
constructor tfilecopy.create(sname,dname:Tfilestream;s,d: integer);
begin
fs:=s;
fd:=d;
fsname:=sname;
fdname:=dname;
inherited create(false);
end;

procedure tfilecopy.Execute;
var
n:integer;
buffer:pointer;
begin
CoInitialize(nil);
freeonterminate:=true;
try
fsname.Position:=fs;
fdname.Position:=fs;
if fd>buffersize then
n:=buffersize else
n:=fd;
getmem(buffer,n);
while not Terminated and (fd <> 0)do
begin
if fd > bufferSize then
N := bufferSize else
N := fd;
fsname.Readbuffer(buffer^,n);
fdname.Writebuffer(buffer^,n);
Dec(fd,N);
end;
finally
FreeMem(Buffer,n);
fsname.free;
fdname.free;
end;
CoUninitialize;
end;

end.
上面是我多线程代码
下面是调用方法:
procedure TForm1.Button1Click(Sender: TObject);

begin
if o1.Execute then
//o1是打开对话框控件
begin
o1.Title:='请选择要复制的源文件!' ;
src:=tfilestream.Create(o1.FileName,fmOpenRead );
end;
if o1.Execute then
begin
o1.Title:='请输入目的文件名!' ;
dec:=tfilestream.Create(o1.FileName,fmCreate);
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
i:integer;
n,k,l:integer;
begin
k:=0;
n:=src.Size div sp.Value-1;
L:=src.Size mod sp.Value;//sp 是个控件返回的是一个整型值,控制线程个数的。
for i:=0 to sp.Valuedo
begin
if i=sp.Value then
n:=n+L;
tfilecopy.create(src,dec,k,n);
k:=k+n;
end;

end;
用一个线程是没问题的,现在用多个后报readstream错误。
 
TStreamAdapter -> IStream ->Clone
 
楼上的什么意思,看不懂
 
线程高手帮忙看看呀!~
 
用一个线程是没问题的,现在用多个后报readstream错误。
来自:zjan521, 时间:2003-9-22 16:35:00, ID:2192731 | 编辑
TStreamAdapter -> IStream ->Clone
TStream非线程安全 所以在多线程读时候失败,
 
如何解决呀~
 
对 来自:shbjkl, 时间:2003-9-22 16:32:00, ID:2192717 稍做修改
建立两个全局的临界区: rlock,wlock:TCriticalSection,创建和释放代码部分省略,修改部分如下:
rlock.Enter;
try
fsname.Readbuffer(buffer^,n);
finally
rlock.Leave;
end;
wlock.Enter;
try
fdname.Writebuffer(buffer^,n);
finally
wlock.Leave;
end;
 
顶部 底部