Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi tFileStream读取和写入之间的循环时间存在巨大差异的原因是什么_Delphi - Fatal编程技术网

Delphi tFileStream读取和写入之间的循环时间存在巨大差异的原因是什么

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

我尝试将股票数据读写到文件中

相同的循环计数会产生巨大的差异。实际的写入循环几乎需要30分钟

这仅仅是因为驱动器写入速度的物理限制吗

有没有办法改进写作过程

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;