2010-12-07 87 views
7

我在2009年的Delphi以下结构:如何在Delphi中将动态数组保存到FileStream中?

type 
    IndiReportIndi = record 
    IndiName: string; 
    NameNum: integer; 
    ReportIndiName: string; 
    end; 

var 
    XRefList: array of IndiReportIndi; 

其中XRefList是一个动态数组。

我想将XRefList保存到FileStream中。我怎么做,并包括所有的IndiName和ReportIndiName字符串,以便他们都将可以再次检索时,我以后从该FileStream加载?

+1

自2010年12月,有一个新的[开放源单元(http://blog.synopse.info/post/2011/03/12/TDynArray和记录比较/加载/保存使用快速RTTI)值得考虑序列化记录或动态数组(具有比序列化更多的功能) - 在Delphi 5中工作到XE2。 – 2011-11-08 07:31:12

回答

6

用途:http://code.google.com/p/kblib/

type 
    IndiReportIndi = record 
    IndiName: string; 
    NameNum: integer; 
    ReportIndiName: string; 
    end; 

    TXRefList = array of IndiReportIndi; 

var 
    XRefList: TXRefList; 

为了节省整个XRefList以流使用:

TKBDynamic.WriteTo(lStream, XRefList, TypeInfo(TXRefList)); 

要加载回:

TKBDynamic.ReadFrom(lStream, XRefList, TypeInfo(TXRefList)); 
10
type 
    IndiReportIndi = record 
    IndiName: string; 
    NameNum: integer; 
    ReportIndiName: string; 
    procedure SaveToStream(Stream: TStream); 
    procedure LoadFromStream(Stream: TStream); 
    end; 

type 
    TXRefList = array of IndiReportIndi; 

function LoadString(Stream: TStream): string; 
var 
    N: Integer; 

begin 
    Result:= ''; 
    Stream.ReadBuffer(N, SizeOf(Integer)); 
    if N > 0 then begin 
    SetLength(Result, N); 
// Stream.ReadBuffer(Result[1], N * SizeOf(Char)); 
// fast version - see comment by A.Bouchez 
    Stream.ReadBuffer(Pointer(Result)^, N * SizeOf(Char)); 
    end; 
end; 

procedure SaveString(Stream: TStream; const S: string); 
var 
    N: Integer; 

begin 
    N:= Length(S); 
    Stream.WriteBuffer(N, SizeOf(Integer)); 
    if N > 0 then 
// Stream.WriteBuffer(S[1], N * SizeOf(Char)); 
// fast version - see comment by A.Bouchez 
    Stream.WriteBuffer(Pointer(S)^, N * SizeOf(Char)); 
end; 

procedure IndiReportIndi.LoadFromStream(Stream: TStream); 
var 
    S: string; 

begin 
    IndiName:= LoadString(Stream); 
    Stream.ReadBuffer(NameNum, SizeOf(Integer)); 
    ReportIndiName:= LoadString(Stream); 
end; 

procedure IndiReportIndi.SaveToStream(Stream: TStream); 
begin 
    SaveString(Stream, IndiName); 
    Stream.WriteBuffer(NameNum, SizeOf(Integer)); 
    SaveString(Stream, ReportIndiName); 
end; 

function LoadXRefList(Stream: TStream): TXRefList; 
var 
    N: Integer; 
    I: Integer; 

begin 
    Stream.ReadBuffer(N, SizeOf(Integer)); 
    if N <= 0 then Result:= nil 
    else begin 
    SetLength(Result, N); 
    for I:= 0 to N - 1 do 
     Result[I].LoadFromStream(Stream); 
    end; 
end; 

procedure SaveXRefList(Stream: TStream; const List: TXRefList); 
var 
    N: Integer; 
    I: Integer; 

begin 
    N:= Length(List); 
    Stream.WriteBuffer(N, SizeOf(Integer)); 
    for I:= 0 to N - 1 do 
    List[I].SaveToStream(Stream); 
end; 
+2

您可以在SaveString中使用指针(Result)^代替LoadString中的Result [1]和指针(S)^,而不是S [1],因为它将保存对UniqueString()的调用。如果在所有情况下使用结果:=''进行编码,则LoadString的速度可能会快一些,如果N> 0,则SetLength(Result,N):所以不会有内存重新分配(使用慢速移动),而是一个字符串finalize then新的分配(这是更快)。 – 2010-12-07 07:39:33

+0

使用TReader/TWriter可以简化标准数据类型的写入。而不是Stream.WriteBuffer(N,SizeOf(Integer));你只需要写Write.WriteInger(N)和N:= Reader.ReadInteger ;.他们也支持字符串和变体,并且代码更具可读性。你只是复制了Delphi已读的代码。 – 2010-12-07 10:07:54

+0

@ldsandon:TReader/TWriter的实现依赖于Delphi版本,并且可能会改变。依靠TReader/TWriter方法实现自己的数据序列化是不可取的。 – kludg 2010-12-07 10:27:16

5
var 
    S: TStream; 
    W: TWriter; 
    A: array of IndiReportIndi; 
    E: IndiReportIndi; 
    ... 
begin 
    S := nil; 
    W := nil; 
    try 
    S := TFileStream.Create(...); 
    W := TWriter.Create(S); 
    W.WriteInteger(Length(A)); 
    for E in A do 
    begin 
     W.WriteString(E.IndiName); 
     W.WriteInteger(E.NameNum); 
     W.WriteString(E.ReportIndiName); 
    end; 
    finally 
    W.Free; 
    S.Free 
    end; 
end; 

读那些你用踏浪号和ReadInteger/ReadString数据。

0

刚的答案是准确的:

考虑在TDynArray包装,这是能够系列化任何考虑看看记录到二进制文件中,也可以记录到/从动态数组中。

有很多类似TList的方法,包括新方法(如哈希或二进制搜索)。

针对速度和磁盘使用进行了非常优化,适用于Delphi 5至XE2以及开放源代码。

参见How to store dynamic arrays in a TList?

0

测试溶液:

procedure TForm1.FormCreate(Sender: TObject); 
VAR Stream: TFileStream; 
    R: IndyRecordIndy; 
begin 
Stream:= TFileStream.Create; 
TRY 
    //put rec in stream 
    Stream.WriteBuffer(R, SizeOf(R)); 

    //restore record from stram 
    Stream.Position := 0; 
    Stream.ReadBuffer(R, Stream.Size); 
FINALLY 
    FreeAndNil(Stream); 
END; 
end 



; 
相关问题