Delphi tFileStream读取和写入之间的循环时间存在巨大差异的原因是什么
我尝试将股票数据读写到文件中 相同的循环计数会产生巨大的差异。实际的写入循环几乎需要30分钟 这仅仅是因为驱动器写入速度的物理限制吗 有没有办法改进写作过程Delphi tFileStream读取和写入之间的循环时间存在巨大差异的原因是什么,delphi,Delphi,我尝试将股票数据读写到文件中 相同的循环计数会产生巨大的差异。实际的写入循环几乎需要30分钟 这仅仅是因为驱动器写入速度的物理限制吗 有没有办法改进写作过程 uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls, Sys
uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls, System.Generics.Collections;
type
tSymbol = record
CloseList: TList<Integer>;
OpenList: TList<Integer>;
VolumeList: TList<Integer>;
end;
TForm1 = class(TForm)
Button1: TButton;
ProgressBar1: TProgressBar;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
ReadList, WriteList: TList<tSymbol>;
end;
procedure TForm1.Button1Click(Sender: TObject); // it takes 45 seconds.
var
_FileStream: TFileStream;
i, j: Integer;
begin
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
ProgressBar1.Min := 0;
ProgressBar1.Max := 999;
_FileStream := TFileStream.Create('test', fmCreate);
for i := 0 to 999 do
begin
for j := 0 to 999 do
begin
_FileStream.Write(WriteList.List[i].CloseList.List[j], 4);
_FileStream.Write(WriteList.List[i].OpenList.List[j], 4);
_FileStream.Write(WriteList.List[i].VolumeList.List[j], 4);
end;
ProgressBar1.Position := i;
end;
_FileStream.Free;
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
end;
procedure TForm1.Button2Click(Sender: TObject); // it takes 6 seconds.
var
_FileStream: TFileStream;
_Close, _Open, _Volume: Integer;
_Symbol: tSymbol;
i, j: Integer;
begin
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
ProgressBar1.Min := 0;
ProgressBar1.Max := 999;
_FileStream := TFileStream.Create('test', fmOpenRead);
for i := 0 to 999 do
begin
_Symbol.CloseList := TList<Integer>.Create;
_Symbol.OpenList := TList<Integer>.Create;
_Symbol.VolumeList := TList<Integer>.Create;
for j := 0 to 999 do
begin
_FileStream.Read(_Close, 4);
_Symbol.CloseList.Add(_Close);
_FileStream.Read(_Open, 4);
_Symbol.OpenList.Add(_Open);
_FileStream.Read(_Volume, 4);
_Symbol.VolumeList.Add(_Volume);
end;
ReadList.Add(_Symbol);
ProgressBar1.Position := i;
end;
_FileStream.Free;
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
end;
procedure TForm1.FormCreate(Sender: TObject);
var
_Symbol: tSymbol;
i, j: Integer;
begin
ReadList := TList<tSymbol>.Create;
WriteList := TList<tSymbol>.Create;
_Symbol.CloseList := TList<Integer>.Create;
_Symbol.OpenList := TList<Integer>.Create;
_Symbol.VolumeList := TList<Integer>.Create;
for i := 0 to 999 do
begin
for j := 0 to 999 do
begin
_Symbol.CloseList.Add(0);
_Symbol.OpenList.Add(0);
_Symbol.VolumeList.Add(0);
end;
WriteList.Add(_Symbol);
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
ReadList.Free;
WriteList.Free;
end;
使用Winapi.Windows、Winapi.Messages、System.SysUtils、System.Variants、System.class、Vcl.Graphics、Vcl.Controls、Vcl.Forms、Vcl.Dialogs、Vcl.ComCtrls、Vcl.StdCtrls、System.Generics.Collections;
类型
tSymbol=记录
关闭列表:TList;
开放列表:TList;
卷列表:TList;
结束;
TForm1=类(TForm)
按钮1:t按钮;
ProgressBar1:TProgressBar;
备忘录1:TMemo;
按钮2:t按钮;
程序按钮1点击(发送方:ToObject);
过程表单创建(发送方:ToObject);
销毁程序表(发送方:TObject);
程序按钮2点击(发送者:对象);
私有的
ReadList,WriteList:TList;
结束;
步骤t用于m1.按钮1单击(发件人:ToObject);//需要45秒。
变量
_FileStream:TFileStream;
i、 j:整数;
开始
备忘录1.Lines.Add(FormatDateTime('hh:mm:ss',Time));
ProgressBar1.Min:=0;
ProgressBar1.最大值:=999;
_FileStream:=TFileStream.Create('test',fmCreate);
对于i:=0到999 do
开始
对于j:=0到999 do
开始
_Write(WriteList.List[i].CloseList.List[j],4);
_Write(WriteList.List[i].OpenList.List[j],4);
_Write(WriteList.List[i].VolumeList.List[j],4);
结束;
ProgressBar1.位置:=i;
结束;
_免费文件流;
备忘录1.Lines.Add(FormatDateTime('hh:mm:ss',Time));
结束;
步骤t用于m1.按钮2单击(发件人:ToObject);//需要6秒钟。
变量
_FileStream:TFileStream;
_关闭,_打开,_卷:整数;
_符号:tSymbol;
i、 j:整数;
开始
备忘录1.Lines.Add(FormatDateTime('hh:mm:ss',Time));
ProgressBar1.Min:=0;
ProgressBar1.最大值:=999;
_FileStream:=TFileStream.Create('test',fmOpenRead);
对于i:=0到999 do
开始
_Symbol.CloseList:=TList.Create;
_Symbol.OpenList:=TList.Create;
_Symbol.VolumeList:=TList.Create;
对于j:=0到999 do
开始
_FileStream.Read(_Close,4);
_Symbol.CloseList.Add(_Close);
_FileStream.Read(_Open,4);
_Symbol.OpenList.Add(_Open);
_读取(卷,4);
_Symbol.VolumeList.Add(_Volume);
结束;
ReadList.Add(_符号);
ProgressBar1.位置:=i;
结束;
_免费文件流;
备忘录1.Lines.Add(FormatDateTime('hh:mm:ss',Time));
结束;
过程TForm1.FormCreate(发送方:TObject);
变量
_符号:tSymbol;
i、 j:整数;
开始
ReadList:=TList.Create;
WriteList:=TList.Create;
_Symbol.CloseList:=TList.Create;
_Symbol.OpenList:=TList.Create;
_Symbol.VolumeList:=TList.Create;
对于i:=0到999 do
开始
对于j:=0到999 do
开始
_符号.关闭列表.添加(0);
_Symbol.OpenList.Add(0);
_Symbol.VolumeList.Add(0);
结束;
WriteList.Add(_符号);
结束;
结束;
程序TForm1.FormDestroy(发送方:ToObject);
开始
免费阅读;
自由撰稿人;
结束;
使用缓冲文件I/O。以较大的块读取/写入文件,根据需要管理每个块中的各个值。Delphi甚至在柏林10.1及更高版本中开设了一门课程
此外,在填充列表时,请提前预分配列表的容量,以避免在向列表中添加新项时必须重新分配列表的内部数组的开销
尝试类似以下内容:
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls, System.Generics.Collections;
type
tSymbol = record
CloseList: TList<Integer>;
OpenList: TList<Integer>;
VolumeList: TList<Integer>;
constructor Create(InitialCapacity: Integer);
procedure Cleanup;
end;
TForm1 = class(TForm)
Button1: TButton;
ProgressBar1: TProgressBar;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
ReadList, WriteList: TList<tSymbol>;
end;
constructor tSymbol.Create(InitialCapacity: Integer);
begin
CloseList := TList<Integer>.Create;
CloseList.Capacity := InitialCapacity;
OpenList := TList<Integer>.Create;
OpenList.Capacity := InitialCapacity;
VolumeList: TList<Integer>.Create;
VolumeList.Capacity := InitialCapacity;
end;
procedure tSymbol.Cleanup;
begin
CloseList.Free;
OpenList.Free;
VolumeList.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
FS: TFileStream;
i, j, idx: Integer;
Block: array of Int32;
begin
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
ProgressBar1.Position := 0;
ProgressBar1.Min := 0;
ProgressBar1.Max := 1000;
ProgressBar1.Step := 1;
FS := T{Buffered}FileStream.Create('test', fmCreate);
try
SetLength(Block, 3 * 1000);
for i := 0 to WriteList.Count-1 do
begin
with WriteList[i] do
begin
idx := 0;
for j := 0 to 999 do
begin
Block[idx+0] := CloseList[j];
Block[idx+1] := OpenList[j];
Block[idx+2] := VolumeList[j];
Inc(idx, 3);
end;
end;
FS.WriteBuffer(Block[0], SizeOf(Int32) * Length(Block));
ProgressBar1.StepIt;
end;
//FS.FlushBuffer;
finally
FS.Free;
end;
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
end;
procedure TForm1.Button2Click(Sender: TObject);
var
FS: TFileStream;
Symbol: tSymbol;
i, j, idx: Integer;
Block: array of Int32;
begin
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
for I := 0 to ReadList.Count-1 do
ReadList[I].Cleanup;
ReadList.Clear;
ProgressBar1.Position := 0;
ProgressBar1.Min := 0;
ProgressBar1.Max := 999;
ProgressBar1.Step := 1;
FS := T{Buffered}FileStream.Create('test', fmOpenRead or fmShareDenyWrite);
try
SetLength(Block, 3 * 1000);
ReadList.Capacity := 1000;
for i := 0 to 999{(FS.Size div 12000) - 1} do
begin
FS.ReadBuffer(Block[0], SizeOf(Int32) * Length(Block));
Symbol := tSymbol.Create(1000);
try
idx := 0;
for j := 0 to 999 do
begin
Symbol.CloseList.Add(Block[idx+0]);
Symbol.OpenList.Add(Block[idx+1]);
Symbol.VolumeList.Add(Block[idx+2]);
Inc(idx, 3);
end;
ReadList.Add(Symbol);
except
Symbol.Cleanup;
raise;
end;
ProgressBar1.StepIt;
end;
finally
FS.Free;
end;
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
end;
procedure TForm1.FormCreate(Sender: TObject);
var
Symbol: tSymbol;
i, j: Integer;
begin
ReadList := TList<tSymbol>.Create;
WriteList := TList<tSymbol>.Create;
WriteList.Capacity := 1000;
for i := 0 to 999 do
begin
Symbol := tSymbol.Create(1000);
try
for j := 0 to 999 do
begin
Symbol.CloseList.Add(0);
Symbol.OpenList.Add(0);
Symbol.VolumeList.Add(0);
end;
WriteList.Add(Symbol);
except
Symbol.Cleanup;
raise;
end;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
i: Integer;
begin
if ReadList <> nil then
begin
for i := 0 to ReadList.Count-1 do
ReadList[i].Cleanup;
ReadList.Free;
end;
if WriteList <> nil then
begin
for i := 0 to WriteList.Count-1 do
WriteList[i].Cleanup;
WriteList.Free;
end;
end;
Delphi TBufferedFileStream只适合在流中向前读写。当你向后阅读时,你会得到比无缓冲更差的性能。对于随机访问,它不会有太大的区别。@dummzeuch:也许是这样,但这些都不适用于这个特定的例子。阅读和写作是线性的和向前的。
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls, System.Generics.Collections;
type
tSymbolValues = record
Close: Integer;
Open: Integer;
Volume: Integer;
end;
tSymbol = record
Values: TList<tSymbolValues>;
constructor Create(InitialCapacity: Integer);
procedure Cleanup;
end;
TForm1 = class(TForm)
Button1: TButton;
ProgressBar1: TProgressBar;
Memo1: TMemo;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
ReadList, WriteList: TList<tSymbol>;
end;
constructor tSymbol.Create(InitialCapacity: Integer);
begin
Values := TList<tSymbolValues>.Create;
Values.Capacity := InitialCapacity;
end;
procedure tSymbol.Cleanup;
begin
Values.Free;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
FS: TFileStream;
i, j, idx: Integer;
Block: array of Int32;
begin
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
ProgressBar1.Position := 0;
ProgressBar1.Min := 0;
ProgressBar1.Max := 1000;
ProgressBar1.Step := 1;
FS := T{Buffered}FileStream.Create('test', fmCreate);
try
SetLength(Block, 3 * 1000);
for i := 0 to WriteList.Count-1 do
begin
with WriteList[i] do
begin
idx := 0;
for j := 0 to Values.Count-1 do
begin
with Values[j] do
begin
Block[idx+0] := Close;
Block[idx+1] := Open;
Block[idx+2] := Volume;
Inc(idx, 3);
end;
end;
end;
FS.WriteBuffer(Block[0], SizeOf(Int32) * Length(Block));
ProgressBar1.StepIt;
end;
//FS.FlushBuffer;
finally
FS.Free;
end;
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
end;
procedure TForm1.Button2Click(Sender: TObject);
var
FS: TFileStream;
Symbol: tSymbol;
Values: tSymbolValues;
i, j, idx: Integer;
Block: array of Int32;
begin
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
for I := 0 to ReadList.Count-1 do
ReadList[i].Cleanup;
ReadList.Clear;
ProgressBar1.Position := 0;
ProgressBar1.Min := 0;
ProgressBar1.Max := 999;
ProgressBar1.Step := 1;
FS := T{Buffered}FileStream.Create('test', fmOpenRead or fmShareDenyWrite);
try
SetLength(Block, 3 * 1000);
ReadList.Capacity := 1000;
for i := 0 to 999{(FS.Size div 12000) - 1} do
begin
FS.ReadBuffer(Block[0], SizeOf(Int32) * Length(Block));
Symbol := tSymbol.Create(1000);
try
idx := 0;
for j := 0 to 999 do
begin
Values.Open := Block[idx+0];
Values.Close := Block[idx+1];
Values.Volume := Block[idx+2];
Symbol.Values.Add(Values);
Inc(idx, 3);
end;
ReadList.Add(Symbol);
except
Symbol.Cleanup;
raise;
end;
ProgressBar1.StepIt;
end;
finally
FS.Free;
end;
Memo1.Lines.Add(FormatDateTime('hh:mm:ss', Time));
end;
procedure TForm1.FormCreate(Sender: TObject);
var
Symbol: tSymbol;
Values: tSymbolValues;
i, j: Integer;
begin
ReadList := TList<tSymbol>.Create;
WriteList := TList<tSymbol>.Create;
WriteList.Capacity := 1000;
for i := 0 to 999 do
begin
Symbol := tSymbol.Create(1000);
try
for j := 0 to 999 do
begin
Values.Open := 0;
Values.Close := 0;
Values.Volume := 0;
Symbol.Values.Add(Values);
end;
WriteList.Add(Symbol);
except
Symbol.Cleanup;
raise;
end;
end;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
i: Integer;
begin
if ReadList <> nil then
begin
for I := 0 to ReadList.Count-1 do
ReadList[i].Cleanup;
ReadList.Free;
end;
if WriteList <> nil then
begin
for I := 0 to WriteList.Count-1 do
WriteList[i].Cleanup;
WriteList.Free;
end;
end;