文件读写速度问题,请高手相助(50分)

  • 主题发起人 主题发起人 peerson
  • 开始时间 开始时间
P

peerson

Unregistered / Unconfirmed
GUEST, unregistred user!
偶是菜鸟,需要进行大量的文本读写,请看下列语句
str:='abcdefghijklmn';
for i:=1 to 1107568 do
writeln(file,str);
这个文本大约21M,写盘时间居然要20″左右,请问高手们,有快速写入文件的好办法吗?
 
用流写文件 先往内存写。。再从内存往文件里写//
 
Genl,能否给个例子,最好有对比数据,谢谢!
 
建议使用TStream数据类型。Delphi7.0在TStringList的性能上较以前的版本更为可靠。
参考代码如下
......
tmpList:=TStringList.Create;
......
for i:=1 to XXXXX do
tmpList.Add(str);
tmpList.SaveToFile(tmpFName);
tmpList.Free;
如果能够将流数据类型和数组变量相结合进行灵活处理,效率可能会更高。
 
LingWing的方法很好,但加上try,finally更完善.

tmpList:=TStringList.Create;
try
for i:=1 to XXXXX do
tmpList.Add(str);
tmpList.SaveToFile(tmpFName);
finally
tmpList.Free;
 
用循环当然慢!! 用流!!!
 
用Tstringlist的方法,速度没有明显的改善,依然需要14″,其中循环体用去5″,继续征求更快速的方法
 
const csize=1024; // csize 为 1024 的倍数
var mbuff:array of char; str:string;
ff:file; i,i1:integer; w:word;
begin
str:='abcdefghijklmn'+#13#10;
w:=length(str);
i:=w*csize;
SetLength(mbuff,i);
i1:=0;
for i:=1 to csize do begin
move(str[1],mbuff[i1],w);
inc(i1,w);
end;
AssignFile(ff,'ttt2.txt');
rewrite(ff,1);
i1:=1107568;
repeat
if i1>csize-1 then i:=csize
else i:=i1;
dec(i1,i);
blockwrite(ff,mbuff[0],i*w);
until i1=0;
closefile(ff);
end;
 
测试了一下,blockwrite(ff,mbuff,i*w); 文件生成的是乱码,
而 blockwrite(ff,mbuff[0],i*w); 是对了。不知道为什么。
 
有请bjdribllec:
您的方法经测试,写入20M数据大约7″,还是提高了很多,不错,在明天中午12:00前如果没有更好的方法出现,将采用并分配分数。
另:
我的程序段主要部分如下,您帮忙看看怎么加入上述的代码,我弄了一下午都出错,呜呜
count:=1;
while not end_flg do
begin
out_str:='';
for j:=0 to n-1 do
begin
.......
end;
inc(count); //计数加1
for i:=0 to m-1 do
begin
if s1[1]='1' then
out_str:=out_str+' '+s1[0]; //得到out_str
end;
//欲在此将out_Str写入文件,请帮忙
end;
 
我用很多的办法测试过,读写文件最快的还是WinAPI
ReadFile,WriteFile,
再Delphi里用简装版
FileRead,FileWrite
 
to 楼主:没有看明白out_str是怎么写出去,在一个while里,这个串要多次以1107568行的方式写到文本文件里吗?
揣测的结果是这样的:
var
mb:array [0..$7fff] of byte;
mfi:integer;
mw,mi1:integer;

mfi:=filecreate('filename');
mw:=0;
count:=1;
while not end_flg do
begin
out_str:='';
for j:=0 to n-1 do
begin
.......
end;
inc(count); //计数加1
for i:=0 to m-1 do
begin
if s1[1]='1' then
out_str:=out_str+' '+s1[0]; //得到out_str
end;
//欲在此将out_Str写入文件,请帮忙
out_str:=out_str+#13#10;
repeat
mi1:=Length(out_Str);
if mi1+mw>sizeof(mb) then mi1:=mi1:=sizeof(mb)-mb;
move(out_str[1],mb[mw],mi1);
delete(out_str,1,mi1);
inc(mw,mi1);
if mw=sizeof(mb) then begin
filewrite(mfi,mb,mw);
mw:=0;
end;
until out_str='';
end;
filewrite(mfi,mb,mw);
fileclose(mfi);
 
用内存映射文件,对付大文件绝对比流快。俱体用法请查找帮助。:)
 
to bjdribllec:
不是的,包括写盘都是在while循环里的,每次生成一个out_str串,整个while循环生成1107568个写入文件
to NeutronDelphi:
能否给个用WINAPI的例子,请针对我的这个问题,谢谢!
 
明白了。mb:array [0..$7fff] of byte; 也可以是 $7ffff
 
用磁盤文件映射文件看看吧
 
procedure WriteToFile(const FileName: string);
var
F: THandle;
P, Buffer: PChar;
S: string;
I, Len, BufLen, BufSize: Integer;
begin
F := FileCreate(FileName, fmCreate);
try
BufSize := 500 * 1024;
Buffer := AllocMem(BufSize);
try
P := Buffer;
BufLen := 0;
S := 'abcdefghijklmn' + sLineBreak;
Len := Length(S);
for I := 0 to 1107568 do
if Len > 0 then
begin
if (BufLen + Len) > BufSize then
begin
FileWrite(F, Buffer^, BufLen);
BufLen := 0;
P := Buffer;
end;
Move(S[1], P^, Len);
Inc(P, Len);
Inc(BufLen, Len);
end;
if BufLen > 0 then
FileWrite(F, Buffer^, BufLen);
finally
FreeMem(Buffer);
end;
finally
CloseHandle(F);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
S: Cardinal;
begin
S := GetTickCount;
WriteToFile('C:/test.txt');
Caption := Format('%f', [(GetTickCount - S) / 1000])
end;
 
感谢QQ在线的帮助,您的实例在我的机器上耗时为6.71″,out_str;='01 02 03 04 05 06'
win98,128M,C3 1.2G 下测试
 
瓶颈在你的组合Out_str和你的文件系统(FAT/FAT32)格式

我是使用NTFS,测试不到0.5秒
 
while not end_flg do
begin
out_str:='';
for j:=0 to n-1 do
begin
.......
end;
inc(count); //计数加1
for i:=0 to m-1 do
begin
if s1[1]='1' then
out_str:=out_str+' '+s1[0]; //得到out_str
end;

不要使用out_str := ...
直接使用静态分配的字符数组,如:Buf: array [0..1024] of Char;
然后对Buf操作。这是其一
其二是你的操作系统的磁盘分区格式,FAT慢,FAT32也慢,NTFS快很多,碎片程序在98, NT, 2000的速度有区别没有?原因之一就是这个分区格式
 

Similar threads

D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部