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 :
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;
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.
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.
Merci ldsandon. Nice et propre et simple. +1.
Utilisation: http://code.google.com/p/kblib/ << Pré> xxx pré>
Pour sauver tout le xreflist en flux Utilisez: p> pour le charger: p>
Ressemble à une très belle routine. Merci de le pointer.
simple TfileStreamex pour enregistrer des variables p>
Je ne connaissais pas la fonction ex. Je vais devoir examiner ça.
juste pour que la réponse soit précise: p>
envisager de regarder le tdynamnarray code>
wrapper, capable de sérialiser n'importe quel enregistrement en binaire, ainsi qu'à / à partir de matrices dynamiques. P>
Il y a beaucoup de méthodes code> de Très optimisé pour l'utilisation de la vitesse et du disque, fonctionne pour Delphi 5 jusqu'à XE2 - et open source. P>
Voir aussi Comment stocker des tableaux dynamiques dans une liste? a> p> code>, y compris de nouvelles méthodes (telles que le hachage ou la recherche binaire). P>
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 ;
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.
Depuis décembre 2010, il y a une nouvelle UNITÉ OPENSOURCE Vaut la peine d'être envisagée pour des enregistrements sérialisés ou des matrices dynamiques (avec beaucoup plus de fonctionnalités que la sérialisation) - Travailler pour Delphi 5 jusqu'à XE2.
@Arnaudbouchez Le lien est mort.
Un lien approprié est maintenant blog.synopse.info/?post/2011/03/12/tdynarray-and-record-compt est / ... - Travailler avec les derniers Delphes, mais aussi avec FPC / LAZARUS.