C# 写入二进制文件花费的时间比 Delphi 长得多

C# writing to binary file taking much longer than Delphi's

我正在将 Delphi 应用程序转换为 C#。程序的一部分需要将Delphi中的许多packed records,或C#中的structs写入一个二进制文件。这些文件大约 400mb。我的 Delphi 版本在 8 seconds 左右完成写入文件,而 C# 版本大约需要 800 seconds。我可以做些什么来提高 C# 版本的速度?

这是 Delphi 版本:

CONST
   RecordSize= 128;
   HeaderSize=128;

TESTrec = packed record
     now: TDateTime;
     //other fields here
     end;

TESThdrrec = packed record
    now: TDateTime;
    Firsttime: TDateTime;
    Lasttime: TDateTime;
    //other fields listed here
    end;

Function TRampBuildForm.CreateTest(FilePath:String;StartTime:TDateTime;EndTime:TDateTime):Boolean;
var
    Records:Int64;
    CurrentOffSet:Int64;
    CurrentTime:TDateTime;
    NewRec:TESTrec;
    NewHeader:TESThdrrec;
    ix:Integer;
    percent:Integer;

begin
    Try
      RampStream:=TFileStream.Create(FilePath,fmCreate OR fmShareExclusive );
    except
      ShowMessage('cannot create Ramp '+Rampname+chr(13)+'Check to see if file is open');
      CreateTest:=false;
    end;
    FillChar(NewHeader,HeaderSize,0);
    NewHeader.now:=Now;
    NewHeader.Firsttime:=StartTime;
    NewHeader.LastTime:= EndTime;
    FirstAllowableTime:=StartTime;
    LastAllowableTime:=EndTime;

    Records:= Round((EndTime-StartTime)/ONE_SECOND)+1;
    RampStream.Write(NewHeader,HeaderSize);

    FillChar(NewRec,RecordSize,0);
    label8.Caption:='Expanding ';
    Progressbar1.Position:=0;
    CurrentTime:=StartTime;
    percent:=0;
    refresh;
    Application.ProcessMessages;
    For ix:= 1 to Records do
    begin
        if (ix*100) div Records > percent then
        begin
            percent:= (ix*100) div Records;
            Progressbar1.position:=percent;
            refresh;
            Application.ProcessMessages
        end;
        NewRec.Now:=CurrentTime;
        RampStream.Write(NewRec,RecordSize);
        CurrentTime:=CurrentTime + ONE_SECOND;
    end;
    ProgressBar1.Position:=100;
    refresh;

    CreateTest:=True;
    RampStream.Free;
end;

我的 C# 版本:

const int RecordSize = 128;
const int HeaderSize = 128;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Testrec
{
    public double now;
    //other fields here
}

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct TESThdrrec
{
    public double now;
    public double Firsttime;
    public double Lasttime;
    //other fields here
}

private Boolean CreateTest(string FilePath, double StartTime, double EndTime)
        {
            long Records;
            long CurrentOffSet;
            double CurrentTime;
            TESTrec NewRec = new TESTrec();
            TESThdrrec NewHeader = new TESThdrrec();
            int ix;
            int percent;

            NewHeader.now = System.DateTime.Now.ToOADate();
            NewHeader.Firsttime = StartTime;
            NewHeader.Lasttime = EndTime;
            FirstAllowableTime = StartTime;
            LastAllowableTime = EndTime;

            if (!File.Exists(FilePath)) //if file doesn't exist
            {
                try
                {
                    using (RampStream = new FileStream(FilePath, FileMode.Create)) 
                    {
                        byte[] buffer = GetBytes2(NewHeader); //puts struct into byte array
                        RampStream.Write(buffer, 0, HeaderSize); //write byte array to file
                    }
                }
                catch (Exception e)
                {
                    System.Windows.MessageBox.Show("Cannot create file" + RampName + Environment.NewLine + "Error Message: " + e);
                }
            }

            Records = (long)(Math.Round((EndTime - StartTime) / ONE_SECOND) + 1);

            RampInfo.Content = "Expanding ";
            ProgressBar1.Value = 0;
            CurrentTime = StartTime;
            percent = 0;

            //TAKING LONG TIME HERE!!
            for (ix = 1; ix <= Records; ix++)
            {
                if (((ix * 100) / Records) > percent)
                {
                    percent = (ix * 100) / (int)Records;
                }
                NewRec.now = CurrentTime;
                using (RampStream = new FileStream(FilePath, FileMode.Open)) 
                {
                    byte[] buffer = GetBytes2(NewRec); //puts struct into byte array
                    RampStream.Write(buffer, 0, RecordSize); //write byte array to file
                }
                //RampStream.Write(NewRec, RecordSize);
                CurrentTime = CurrentTime + ONE_SECOND;
            }

            ProgressBar1.Value = 100;

            RampStream.Close();
            return true;
        }

for loop 中有一个正在更新的进度条,这是代码挂起的地方。我没有刷新它或使用 Delphi 版本正在使用的 FillChar 等价物,但我认为这不会影响它?

您正在为每次写入打开和关闭流!在写入循环开始时打开文件一次,并在循环结束时关闭它(就像您在旧代码中所做的那样)。

(您需要确保您仍在使用 using 语句关闭文件。)