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.