How to save/load Set of Types?

后端 未结 9 1335
傲寒
傲寒 2020-12-06 00:47

I have this code

type
  TXSample = (xsType1, xsType2, xsType3, xsType4, xsType5, xsType6, xsType6, xsTyp7, xsType8); // up to FXSample30;  
..

private
  FX         


        
9条回答
  •  被撕碎了的回忆
    2020-12-06 01:24

    Set variables can be saved successfully to a TStream descendant. Here's an example.

    Just create a new vcl forms application, add two TButton components to it and fill in the OnClick events for each button as illustrated in the example below.

    This was created in XE4 so the uses clause might be different for other versions of Delphi but that should be trivial to change by removing the namespace indicators before each unit in the uses clause. Saving a set type variable with articulated values is possible to a binary file and easily with Delphi. In other words,

    Also suggested is taking a look at the TypInfo unit if you have the source or just using the functions provided which make dissecting Set types down to their text representation fairly simple though no example is provided here. That is suggested if you want to include saving to a config or ini file or in a persistence format that is text editable.

    The one below is the simplest one that I know of. Looking at the binary output of a set type saved to a stream like the one below implies that it is saved in the smallest possible bitmapped representation for the set based on its size. The one below maps to one byte on disk (the value is 5) which means that each value must be mapped to a power of 2 (seThis = 1, seThat = 2, seTheOther = 4) just like manually created constant bitmasked values. The compiler likely enforces that it follows rules that forces set to retain their ordinality. This example was tested an works in Delphi XE4.

    Hope that helps.

    Brian Joseph Johns

    unit Unit1;
    
    interface
    
    uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
         Vcl.StdCtrls;
    
    type
      TSomeEnum = (seThis, seThat, seTheOther);
      TSomeEnumSet = set of TSomeEnum;
    
      TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
    
      Form1: TForm1;
      SomeSetVar: TSomeEnumSet;
      SomeBoolean: Boolean;
      SomeInt: Integer;
    
    implementation
    
    {$R *.dfm}
    
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      SomeSetVar := [seThis, seTheOther];
      SomeBoolean := True;
      SomeInt := 31415;
    
      with TFileStream.Create('SetSave.bin',fmCreate or fmOpenWrite or fmShareCompat) do
      try
        Write(SomeSetVar,SizeOf(SomeSetVar));
        Write(SomeBoolean,SizeOf(Boolean));
        Write(SomeInt,SizeOf(Integer));
      finally
        Free;
      end;
      SomeSetVar := [];
      SomeInt := 0;
      SomeBoolean := False;
    
    end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    var
      ResponseStr: string;
    begin
      with TFileStream.Create('SetSave.bin',fmOpenRead or fmShareCompat) do
      try
        Read(SomeSetVar,SizeOf(SomeSetVar));
        Read(SomeBoolean,SizeOf(Boolean));
        Read(SomeInt,SizeOf(Integer));
      finally
        Free;
      end;
    
      ResponseStr := 'SomeSetVar = ';
      if (seThis in SomeSetVar) then
        ResponseStr := ResponseStr + 'seThis ';
    
      if (seThat in SomeSetVar) then
        ResponseStr := ResponseStr + 'seThat ';
    
      if (seTheOther in SomeSetVar) then
        ResponseStr := ResponseStr + 'seTheOther ';
    
      ResponseStr := ResponseStr + ' SomeBoolean = ' + BoolToStr(SomeBoolean);
    
      ResponseStr := ResponseStr + ' SomeInt = ' + IntToStr(SomeInt);
    
      ShowMessage(ResponseStr);
    
    end;
    
    end.
    

提交回复
热议问题