如何将结构写入流?

时间:2011-11-08 04:15:49

标签: delphi

我可以,还是必须使用自己的SaveToStream方法将其声明为一个类?

只有数据,没有功能(虽然我现在可能会添加getter& setters)

2 个答案:

答案 0 :(得分:8)

https://github.com/KrystianBigaj/kblib - 您可以尝试这一点(无需将字符串限制为常量,并使用复杂记录,使用一行加载/保存)。

类似的问题:

答案 1 :(得分:5)

假设您有以下记录

type
  TMyRecord = record
    FirstName: string[100]; // 100 characters max. for First name
    LastName: string[100]; // 100 characters max. for Last name
    Age: Byte;
    DateOfBirth: TDateTime;
  end;
const
  // if you are using Delphi 2009 and above, 
  // then either change *string[100]* to *AnsiString[100]* or use a different
  // approach to save the string, read bellow
  szMyRecord = SizeOf( TMyRecord ); // storing it will make your code run faster if you write a lot of records

现在,为了将上述结构写入流,您需要:

procedure WriteRecord(
  const ARecord: TMyRecord;
  const AStream: TStream // can be a TMemoryStream, TFileStream, etc.
);
begin
  AStream.Write(ARecord, szMyRecord);
end;

重要的是要注意,将FirstName声明为“string”将不会保存FirstName中的字符,您需要声明FirstName,因为我执行了“string [100]”或使用特殊方法来编写字符串字段,例如:

type
  TMyRecordWithVeryLongStrings = record
    LenFirstName: Integer; // we store only the length of the string in this field
    LenLastName: Integer; // same as above
    Age: Byte;
    DateOfBirth: TDateTime;
    FirstName: string; // we will ignore this field when writing, using it for value
    LastName: string; // same as above
  end;

const
  // we are ignoring the last two fields, since the data stored there is only a pointer,
  // then we can safely assume that ( SizeOf( string ) * 2 ) is the offset
  szMyRecordWithVeryLongStrings = SizeOf( TMyRecordWithVeryLongStrings ) - ( SizeOf( string ) * 2 );

// the difference between this method and above is that we first write the record
// and then the strings
procedure WriteRecord(
  ARecord: TMyRecordWithVeryLongStrings;
  AStream: TStream // can be a TMemoryStream, TFileStream, etc.
);
const szChar = sizeof(char);
begin
  // ensure the length of first and Last name are stored in "Len + Name" field
  ARecord.LenFirstName := Length( ARecord.FirstName );
  ARecoord.LenLastName := Length( ARecord.Lastname );
  // write the record
  AStream.Write(ARecord, szMyRecordWithVeryLongStrings);
  // write First name value
  AStream.Write(
    Pointer( ARecord.FirstName )^, // value of first name
    szChar * ARecord.LenFirstName
  );
  // repeat as above for last name
  AStream.Write(
    Pointer( ARecord.LastName )^, // value of first name
    szChar * ARecord.LenLastName
  );
end;

现在,为了阅读“长字符串”,您首先阅读记录:

procedure ReadRecord(
  ARecord: TMyRecordWithVeryLongStrings;
  AStream: TStream
);
begin
  AStream.Read(Arecord, szMyRecordWithVeryLongStrings );
  // now read first and last name values which are right after the record in the stream
  AStream.Read(Pointer(ARecord.FirstName)^, szChar * ARecord.LenFirstName );
  AStream.Read(Pointer(ARecord.,LastrName)^, szChar * ARecord.LenLastName );
end;

我希望它有所帮助(: