0

我通过序列化和反序列化表单及其内容到Delphi编写了以下代码

unit SerAndDeser;

interface

  uses Classes,MainForm,ListOfTables,DataOfTable,SerialForms,sysutils,ActiveX, DatabaseClasses, UnloadProcs;

  procedure Ser();
  procedure Deser();
  function GetGUID(): string;
  function DeleteSymbols(inputstr : string) : string;
implementation

  function GetGUID(): string;
  var
  GUID : TGUID;
  begin
  Result := '';
  if CoCreateGuid(GUID) = 0 then
    Result := GUIDToString(GUID);
    Result := StringReplace(Result, '{', '', []);
    Result := StringReplace(Result, '}', '', []);
    Result := StringReplace(Result, '-', '', [rfReplaceAll]);
  end;

  function DeleteSymbols(inputstr : string): string;
  begin
  Result := '';
    Result := StringReplace(inputstr, '-', '', [rfReplaceAll]);
    Result := StringReplace(Result, ' ', '', [rfReplaceAll]);
    Result := StringReplace(Result, '\', '', [rfReplaceAll]);
    Result := StringReplace(Result, '/', '', [rfReplaceAll]);
  end;

  procedure Ser();

    var mForm : MainFormInfo;
        tForm : TableFormInfo;
        lForm : ListFormInfo;
        tempFmtable : TfmTableData;
        i,j : integer;
        MyFileStream : TFileStream;
        MyMemoryStream : TMemoryStream;
        field : TableFieldInfo;
  begin
        try
      mForm := nil;

      mForm := MainFormInfo.Create(
        nil,
        MainWindow.Left,
        MainWindow.Top,
        MainWindow.Height,
        MainWindow.Width,
        MainWindow.partofconnectstring,
        MainWindow.dbname,
        MainWindow.dbfilename);
      mForm.Name := 'MainWindow';

      //table forms
      try
        tForm := nil;
        field := nil;

        for i := 0 to MainWindow.ComponentCount - 1 do
          if (MainWindow.Components[i] is TfmTableData) then
            begin
              tempFmtable := MainWindow.Components[i] as TfmTableData;
              tForm := TableFormInfo.Create(
                mForm,
                tempFmtable.Left,
                tempFmtable.Top,
                tempFmtable.Height,
                tempFmtable.Width,
                tempFmtable.tname);
              tForm.Name := tempFmtable.Name;

              //fields
              for j := 0 to tempFmtable.DBGrid1.Columns.Count - 1 do
              begin
                field := nil;

                field := TableFieldInfo.Create(
                  tForm,
                  tempFmtable.DBGrid1.Columns[j].FieldName,
                  tempFmtable.DBGrid1.Columns[j].Title.Caption,
                  tempFmtable.DBGrid1.Columns[j].Index,
                  tempFmtable.DBGrid1.Columns[j].Visible);
                  field.Name := DeleteSymbols(tempFmtable.DBGrid1.Columns[j].FieldName);{tempFmtable.DBGrid1.Columns[j].FieldName} {+ GetGUID;}
              end;
              //

            end;
      except
        field.Free;
        tForm.Free;
      end;
      //

      //List form
      try
        lForm := nil;
        lForm := ListFormInfo.Create(
          mForm,
          fmListOfTables.Left,
          fmListOfTables.Top,
          fmListOfTables.Height,
          fmListOfTables.Width);
        lForm.Name := 'fmListOfTables';
      except
        lForm.Free;
      end;
      //

      //save
      MyFileStream := nil;
      MyMemoryStream := nil;

      MyFileStream := TFileStream.Create('test.txt', fmCreate);
      MyMemoryStream := TMemoryStream.Create;
      MyMemoryStream.WriteComponent(mForm);
      MyMemoryStream.Position := 0;
      ObjectBinaryToText(MyMemoryStream,MyFileStream);
      MainWindow.Panel1.DockManager.SaveToStream(MyFileStream);
      //

    finally
      mForm.Free;
      MyFileStream.Free;
      MyMemoryStream.Free;
    end;
  end;


  procedure Deser();

    var mForm : MainFormInfo;
        tForm : TableFormInfo;
        lForm : ListFormInfo;
        tempFmtable : TfmTableData;
        i,j : integer;
        MyFileStream : TFileStream;
        MyMemoryStream : TMemoryStream;
        table : TTableSpec;
        descr : string;
        field : TableFieldInfo;


  begin
    try
      //destroy environment
      i := 0;
      while (i <= MainWindow.ComponentCount - 1) do
      begin
        if MainWindow.Components[i] is TfmTableData then
          try
            tempFmTable := nil;
            tempFmTable := MainWindow.Components[i] as TfmTableData;
            tempFmTable.IBQuery1.Close;
            tempFmtable.Free;
          except
            tempFmTable.Free;
          end
        else
          inc(i);
      end;
      fmListOfTables.Free;
      DBSchema.Free;
      //

      //read
      mForm := nil;
      MyFileStream := nil;
      MyMemoryStream := nil;

      mForm := MainFormInfo.Create(nil, -1, -1, -1, -1, MainWindow.partofconnectstring, MainWindow.dbname, MainWindow.dbfilename);

      MyFileStream := TFileStream.Create('test.txt', fmOpenRead);
      MyMemoryStream := TMemoryStream.Create;
      ObjectTextToBinary(MyFileStream,MyMemoryStream);
      MyMemoryStream.Position := 0;
      MyMemoryStream.ReadComponent(mForm);
      //

      //go
      UnloadProcs.ConnectToDatabase(MainWindow.partofconnectstring, MainWindow.SQLConnection1);
      //UnloadProcs.CreateObjs(MainWindow.SQLConnection1, MainForm.DBSchema);
      //fmListOfTables.Show;

      MainWindow.Left := mForm.LeftValue;
      MainWindow.Top := mForm.TopValue;
      MainWindow.Height := mForm.HeightValue;
      MainWindow.Width := mForm.WidthValue;

      //list
      i := 0;
      while i <= mForm.ComponentCount - 1 do
      begin
        if mForm.Components[i] is ListFormInfo then
          try
            lForm := nil;
            lForm := mForm.Components[i] as ListFormInfo;
            fmListOfTables.Left := lForm.LeftValue;
            fmListOfTables.Top := lForm.TopValue;
            fmListOfTables.Height := lForm.HeightValue;
            fmListOfTables.Width := lForm.WidthValue;
            fmListOfTables.Show;
            inc(i);
          finally
            lForm.Free;
          end
        else
          inc(i);
      end;
      //

      //fmListOfTables.Show;
      //tables
      for j := 0 to mForm.ComponentCount - 1 do
        if mForm.Components[j] is TableFormInfo then
          try
            table := nil;
            tempFmtable := nil;
            tForm := nil;

            tForm := mForm.Components[j] as TableFormInfo;

            table := TTableSpec(DBSchema.Tables.FindComponent(tForm.Table));
            tempFmtable := TfmTableData.Create(MainWindow);
            tempFmtable.Name := tForm.Name;
            tempFmtable.tname := tForm.Table;
            //tempFmtable.Caption := Utf8ToAnsi(table.Description);
            tempFmtable.Left := tForm.LeftValue;
            tempFmtable.Top := tForm.TopValue;
            tempFmtable.Height := tForm.HeightValue;
            tempFmtable.Width := tForm.WidthValue;

            tempFmTable.IBQuery1.SQL.Clear;
            tempFmtable.IBQuery1.SQL.Add('select * from ' + table.Name);
            tempFmtable.IBQuery1.Open;

            i := 0;
            while i <= tForm.ComponentCount - 1 do
              if tForm.Components[i] is TableFieldInfo then
              begin
                field := nil;

                field := tForm.Components[i] as TableFieldInfo;
                tempFmtable.DBGrid1.Columns[i].FieldName := field.FieldNameValue;
                tempFmtable.DBGrid1.Columns[i].Title.Caption := field.DescriptionValue;
                tempFmtable.DBGrid1.Columns[i].Index := field.IndexValue;
                tempFmtable.DBGrid1.Columns[i].Visible := field.VisibleValue;
                //tempFmtable.CheckListBox1.Items.Add(field.Description);
                //tempFmtable.CheckListBox1.Checked[i] := field.Visible;
                inc(i);
              end
              else
                inc(i);

            {for i := 0 to table.Fields.ComponentCount - 1 do
            begin
              descr := Utf8ToAnsi(((table.Fields.Components[i]) as TFieldSpec).Description);
              tempFmtable.CheckListBox1.Items.Add(descr);
              tempFmtable.DBGrid1.Columns[i].Title.Caption := descr;
              tempFmtable.CheckListBox1.Checked[i] := true;
            end; }

            tempFmtable.Show;


          except
            tempFmtable.Free;
            tForm.Free;
            table.Free;
          end;
      //

      //dock
      MainWindow.Panel1.DockManager.BeginUpdate;
      MainWindow.Panel1.DockManager.LoadFromStream(MyFileStream);
      MainWindow.Panel1.DockManager.ResetBounds(TRUE);
      MainWindow.Panel1.DockManager.EndUpdate;


      //
    finally
      MyFileStream.Free;
      MyMemoryStream.Free;
    end;

  end;

end.

调试时我发现给出了

'Project GUI.exe raised exception class $C0000005 with message 'access violation at 0x00821dae: read of address 0x00000044'. 

线上异常

tempFmtable.IBQuery1.SQL.Add('select * from ' + table.Name);

在以下代码块中的代码更高

  //tables
  for j := 0 to mForm.ComponentCount - 1 do
    if mForm.Components[j] is TableFormInfo then
      try
        table := nil;
        tempFmtable := nil;
        tForm := nil;

        tForm := mForm.Components[j] as TableFormInfo;

        table := TTableSpec(DBSchema.Tables.FindComponent(tForm.Table));
        tempFmtable := TfmTableData.Create(MainWindow);
        tempFmtable.Name := tForm.Name;
        tempFmtable.tname := tForm.Table;
        //tempFmtable.Caption := Utf8ToAnsi(table.Description);
        tempFmtable.Left := tForm.LeftValue;
        tempFmtable.Top := tForm.TopValue;
        tempFmtable.Height := tForm.HeightValue;
        tempFmtable.Width := tForm.WidthValue;

        tempFmTable.IBQuery1.SQL.Clear;
        tempFmtable.IBQuery1.SQL.Add('select * from ' + table.Name);
        tempFmtable.IBQuery1.Open;

        i := 0;
        while i <= tForm.ComponentCount - 1 do
          if tForm.Components[i] is TableFieldInfo then
          begin
            field := nil;
            //tempFmtable.Show;
            field := tForm.Components[i] as TableFieldInfo;
            tempFmtable.DBGrid1.Columns[i].FieldName := field.FieldNameValue;
            tempFmtable.DBGrid1.Columns[i].Title.Caption := field.DescriptionValue;
            tempFmtable.DBGrid1.Columns[i].Index := field.IndexValue;
            tempFmtable.DBGrid1.Columns[i].Visible := field.VisibleValue;
            //tempFmtable.CheckListBox1.Items.Add(field.Description);
            //tempFmtable.CheckListBox1.Checked[i] := field.Visible;
            //tempFmtable.Show;
            inc(i);
          end
          else
            inc(i);

        {for i := 0 to table.Fields.ComponentCount - 1 do
        begin
          descr := Utf8ToAnsi(((table.Fields.Components[i]) as TFieldSpec).Description);
          tempFmtable.CheckListBox1.Items.Add(descr);
          tempFmtable.DBGrid1.Columns[i].Title.Caption := descr;
          tempFmtable.CheckListBox1.Checked[i] := true;
        end; }

        tempFmtable.Show;


      except
        tempFmtable.Free;
        tForm.Free;
        table.Free;
      end;
4

1 回答 1

2

失败的行是:

tempFmtable.IBQuery1.SQL.Add('select * from ' + table.Name);

在此行运行之前,您分配table如下:

table := TTableSpec(DBSchema.Tables.FindComponent(tForm.Table));

似乎FindComponent又回来了nil

我相信你知道,你必须有一个有效的对象实例才能调用方法、访问字段和属性等。你的代码应该检查这个条件并做出相应的响应。

您可以在调试器中很容易地看到所有这些。调试器将在该行中断,当您检查变量时,它会告诉您tablenil. 然后你必须查看代码并找出原因。我建议您花一些时间提高您的调试技能并学习如何使用可用的工具。

于 2012-12-15T16:22:07.037 回答