2011-11-08 53 views
1

我可以,还是必须将其声明为具有自己的SaveToStream方法的类?如何将结构写入流?

它是唯一的数据,没有功能(虽然我现在可能添加的getter & setter方法)

+2

可能重复(http://stackoverflow.com/questions/4533376/写复杂的记录到文件) –

回答

4

假设你有以下记录现在

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声明为“st环”将不保存在名字中的字符,你需要声明名字和我一样‘的字符串[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; 

我希望它有助于(:

+0

+1,并感谢这样一个全面的例子!我将复制/粘贴并测试它,并在我得到它的时候给予答案。谢谢 !! – Mawg

+3

请注意,这只适用于短字符串(字符串[xx])。他们只是Ansi。所有其他的字符串都是指针,你需要更多的工作来写它们。 –

+0

ShortStrings自从2009年德尔福以来真的被弃用了。这是恕我直言,不是记录保存的好选择,而且会浪费太多空间。 –

8

http://code.google.com/p/kblib/ - 你可以试试这个(没有必要限制字符串常量的大小和复杂的工作记录,加载/保存一行)。

类似的问题:的[编写复杂的记录到文件]

+3

+1,因为您确定了重复的问题。也许值得添加到列表[这个OpenSource单元](http://blog.synopse.info/post/2011/03/12/TDynArray-and-Record-compare/load/save-using-fast-RTTI) - 为Delphi 5工作到XE2。 –

+0

@Arnaud Bouchez - 谢谢,我添加了kblib主页的链接:) – kibab

+1

+1谢谢soem很棒的链接 – Mawg