7
votes

Comment puis-je enregistrer une matrice dynamique à un filtream à Delphi?

J'ai les structures suivantes à DELPHI 2009:

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

var
  XRefList: array of IndiReportIndi;


6 Réponses :


10
votes
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;

4 commentaires

Vous auriez pu utiliser le pointeur (résultat) ^ au lieu du résultat [1] dans le chargement et le (s) pointeur (s) ^ au lieu de S [1] dans Savestring, car il enregistre un appel à unique (). Loadstring pourrait également être un peu plus rapide si codé avec le résultat: = '' Dans tous les cas, puis setLength (résultat, n) si N> 0: il n'y aura pas de réallocation de mémoire (avec une chaîne finale), mais une chaîne finalise alors nouvelle allocation (ce qui est plus rapide).


Utilisez un pédalier / Twriter pour simplifier l'écriture de types de données standard. Au lieu de stream.writebuffer (n, taille de (entier)); vous écririez simplement écrire.writeinger (n) et n: = Reader.readinteger ;. Ils ont également un soutien pour les chaînes et les variantes, et le code est beaucoup plus lisible. Vous venez de dupliquer le code Delphi Delphi Alead a.


@LDSANDON: La mise en œuvre du pédalier / Twriter dépend de la version Delphi et peut changer. Il n'est pas souhaitable de s'appuyer sur les méthodes de pédalier / Twriter pour mettre en œuvre votre propre sérialisation de données.


La structure d'enregistrement OP changera également - et votre code dépend également de la version de Delphi. Si le fichier doit être utilisé sur une application compilée avec une version différente de DelphI, un en-tête contenant des informations de version doit être ajouté pour permettre à l'application de lecture d'utiliser les fonctions de lecture correctes.



5
votes
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;  
To read those data you use a TReader and ReadInteger/ReadString.

1 commentaires

Merci ldsandon. Nice et propre et simple. +1.



6
votes

Utilisation: http://code.google.com/p/kblib/ << Pré> xxx

Pour sauver tout le xreflist en flux Utilisez: xxx

pour le charger: xxx


1 commentaires

Ressemble à une très belle routine. Merci de le pointer.




0
votes

juste pour que la réponse soit précise:

envisager de regarder le tdynamnarray wrapper, capable de sérialiser n'importe quel enregistrement en binaire, ainsi qu'à / à partir de matrices dynamiques.

Il y a beaucoup de méthodes de , y compris de nouvelles méthodes (telles que le hachage ou la recherche binaire).

Très optimisé pour l'utilisation de la vitesse et du disque, fonctionne pour Delphi 5 jusqu'à XE2 - et open source.

Voir aussi Comment stocker des tableaux dynamiques dans une liste?


0 commentaires

0
votes

Solution testée:

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



;


1 commentaires

Ceci est une erreur! Vous enregistrez les pointeurs sur les chaînes du fichier. Ce sont des données inutiles la prochaine fois que vous lisez le fichier.