saving a records containing a member of type string to a file (Delphi, Windows)

后端 未结 5 1721
情书的邮戳
情书的邮戳 2020-12-22 06:13

I have a record that looks similar to:

type
  TNote = record
    Title : string;
    Note  : string;
    Index : integer;
  end;

Simple. Th

5条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-22 07:04

    You can't do it with a typed file. Try something like this, with a TFileStream:

    type
       TStreamEx = class helper for TStream
       public
          procedure writeString(const data: string);
          function readString: string;
          procedure writeInt(data: integer);
          function readInt: integer;
      end;
    
    function TStreamEx.readString: string;
    var
       len: integer;
       iString: UTF8String;
    begin
       self.readBuffer(len, 4);
       if len > 0 then
       begin
          setLength(iString, len);
          self.ReadBuffer(iString[1], len);
          result := string(iString);
       end;
    end;
    
    procedure TStreamEx.writeString(const data: string);
    var
       len: cardinal;
       oString: UTF8String;
    begin
       oString := UTF8String(data);
       len := length(oString);
       self.WriteBuffer(len, 4);
       if len > 0 then
          self.WriteBuffer(oString[1], len);
    end;
    
    function TStreamEx.readInt: integer;
    begin
       self.readBuffer(result, 4);
    end;
    
    procedure TStreamEx.writeInt(data: integer);
    begin
       self.WriteBuffer(data, 4);
    end;
    
    type
      TNote = record
        Title : string;
        Note  : string;
        Index : integer;
        procedure Save(stream: TStream);
      end;
    
    procedure TNote.Save(stream: TStream);
    var
       temp: TMemoryStream;
    begin
       temp := TMemoryStream.Create;
       try
          temp.writeString(Title);
          temp.writeString(Note);
          temp.writeInt(Index);
          temp.seek(0, soFromBeginning);
          stream.writeInt(temp.size);
          stream.copyFrom(temp, temp.size);
       finally
          temp.Free;
       end;
    end;
    

    I'll leave the Load procedure to you. Same basic idea, but it shouldn't need a temp stream. With the record size in front of each entry, you can read it and know how far to skip if you're looking for a certain record # instead of reading the whole thing.

    EDIT: This was written specifically for versions of Delphi that use Unicode strings. On older versions, you could simplify it quite a bit.

提交回复
热议问题