Précédent   Forum des professionnels en informatique > Autres langages > Pascal > Lazarus
Lazarus Forum d'entraide sur Lazarus, l'EDI RAD multiplateforme basé sur Free Pascal
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
Vieux 06/02/2010, 23h28   #1
Membre actif
 
Avatar de ChPr
 
Inscription : septembre 2005
Messages : 478
Détails du profil
Informations personnelles :
Âge : 66

Informations forums :
Inscription : septembre 2005
Messages : 478
Points : 175
Points : 175
Par défaut Ajouter un enregistrement à un fichier

Bonsoir à toutes et à tous,

Avec la procédure Append, il est possible d'ajouter du texte à la fin d'un fichier ... Texte.

Cette procédure ne fonctionne pas pour les autres types de fichiers. Or j'ai un fichier composé d'enregistrements (record) et je voudrais y ajouter toutes les X minutes un nouvel enregistrement sans avoir à ré-enregistrer tout le fichier et que cela fonctionne sous Windows et sous Linux.

Je n'ai pas trouvé de méthodes pour cela (peut-être mal cherché). En existe-t-il ?

J'ai essayé un transtypage :

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
type
  TVals = record
    A, B: Integer;
  end;
 
var
  Vals: TVals
  F: Text;
...
AssignFile(F, MonFichier);
Append(F);
Write (F, string(Vals.A)+string(Vals.B)); {Plantage}
...
ça compile, mais ça plante à l'exécution. Il faut peut-être que je passe par un buffer ?

Merci de votre aide.

Pierre

Dernière modification par ChPr ; 06/02/2010 à 23h40.
ChPr est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2010, 00h03   #2
Membre émérite
 
Avatar de Dr.Who
 
Inscription : septembre 2009
Messages : 825
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : septembre 2009
Messages : 825
Points : 905
Points : 905
TFileStream!

Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
// creation
with TFileStream.Create(fileName, fmOpenReadWrite) do
try
  // on vas a la fin
  Position := Size;
  // on ecrit
  Write(Value, SizeOf(TValue));
finally
  // on libère
  Free;
end;
__________________
[ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
Ma messagerie n'est pas la succursale du forum... merci!

Dernière modification par Dr.Who ; 08/02/2010 à 01h13.
Dr.Who est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2010, 10h40   #3
Membre éclairé
 
Homme
Inscription : janvier 2010
Messages : 192
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 39
Localisation : France, Gironde (Aquitaine)

Informations forums :
Inscription : janvier 2010
Messages : 192
Points : 365
Points : 365
Methode 1 : Lire tous les enregistrement du fichiers puis ajouter.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
program FileTest;
 
uses SysUtils;
 
type 
  TVals=record
    A, B : Integer;
  end;
 
var
  Vals : TVals;
  F : file of TVals;
  I : Integer = 0;
begin
  Assign(F,'vals.bin');
  FileMode:=fmOpenReadWrite;
  Reset(F);  
  while not Eof(F) do
  begin
    Read(F, Vals);
    WriteLn(I, ': A=', Vals.A, ' B=', Vals.B);
    I := I + 1;
  end;
 
  Write('A='); ReadLn(Vals.A);
  Write('B='); ReadLn(Vals.B);
  Write(F,Vals);
end.
Methode 2 : Fonctions 'File*'
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
program FileAppend;
 
uses SysUtils;
 
type 
  TVals=record
    A, B : Integer;
  end;
 
var
  Vals : TVals;
  F : LongInt;
begin
  F := FileOpen('vals.bin', fmOpenReadWrite);
  FileSeek(F, 0, fsFromEnd);  
 
  Write('A='); ReadLn(Vals.A);
  Write('B='); ReadLn(Vals.B);
 
  FileWrite(F,Vals, SizeOf(TVals));
 
  FileClose(F);
end.
batyann811 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2010, 19h18   #4
Membre actif
 
Avatar de ChPr
 
Inscription : septembre 2005
Messages : 478
Détails du profil
Informations personnelles :
Âge : 66

Informations forums :
Inscription : septembre 2005
Messages : 478
Points : 175
Points : 175
Merci pour les solutions que vous m'apportez.

Pour le moment, j'ai choisi d'utiliser "TFileStream".

Par contre, il ne faut pas faire : mais : Cordialement.

Pierre
ChPr est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2010, 01h13   #5
Membre émérite
 
Avatar de Dr.Who
 
Inscription : septembre 2009
Messages : 825
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : septembre 2009
Messages : 825
Points : 905
Points : 905
exact
__________________
[ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
Ma messagerie n'est pas la succursale du forum... merci!
Dr.Who est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2010, 01h27   #6
Membre émérite
 
Avatar de Dr.Who
 
Inscription : septembre 2009
Messages : 825
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : septembre 2009
Messages : 825
Points : 905
Points : 905
et cerise sur le gateau avec TFileStream :


Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 
type
  TVal = packed record
    A, B: integer;
  end;
  PVals = ^TVals;
  TVals = array of TVal;
 
procedure ValsSave(FileName: string; lpVals: PVals);
var
  vCount : integer;
  vSize : integer;
begin
  with TFileStream.Create(FileName, fmCreate) do
  try
    vCount := Length(lpVals^);
    vSize := vCount * SizeOf(TVal);
    Write(vCount, 4);
    Write(vSize, 4);
    Write(lpVals^, vSize); 
  finally
    Free;
  end;
end;
 
procedure ValsLoad(FileName: string; lpVals: PVals);
var vCount, vSize: integer;
begin
  with TFileStream.Create(FileName, fmOpenRead) do
  try
    read(vCount, 4);
    read(vSize, 4);
 
    assert(vSize <> (vCount*SizeOf(TVal)), 'Size not match');
 
    SetLength(lpVals^, vCount);
    read(lpVals^, vSize);
  finally
    Free;
  end;
end;
__________________
[ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
Ma messagerie n'est pas la succursale du forum... merci!
Dr.Who est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2010, 09h53   #7
Membre éclairé
 
Homme
Inscription : janvier 2010
Messages : 192
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 39
Localisation : France, Gironde (Aquitaine)

Informations forums :
Inscription : janvier 2010
Messages : 192
Points : 365
Points : 365
Après consultation d'un bouquin la bonne méthode pour ajouter des données à la fin d'un 'file of Type' c'est :

Code :
1
2
3
4
5
6
7
8
  Assign(F,'vals.bin');
  Reset(F); // Ouvre en lecture/écriture
 
  Seek(F, FileSize(F)); // Aller à la fin
 
  Write(F,Vals);  // Ecrire
 
  Close(F);
batyann811 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2010, 15h31   #8
Membre actif
 
Avatar de ChPr
 
Inscription : septembre 2005
Messages : 478
Détails du profil
Informations personnelles :
Âge : 66

Informations forums :
Inscription : septembre 2005
Messages : 478
Points : 175
Points : 175
Merci pour ces compléments d'info.

Cependant, j'ai un problème avec la méthode que préconise "batyann811".

Le fichier "original" que je récupère auquel je dois rajouter des valeurs est constitué de N enregistrements de X octets suivi d'un enregistrement de taille différente (Y octets).

Avec TFileStream, cela ne me pose pas de problème car "Size" me retourne le nombre d'octets du fichier. Je vais donc à la fin moins Y octets, j'écris mes enregistrements de X octets et je peux y rajouter au final l'enregistrement de Y octets (mais je ne le fais pas car cela ne me sert à rien).

Avec Assign(F, 'MonFichier'), "FileSize" me retourne un nombre d'enregistrements de la taille du type de F (soit X octets dans mon cas). Je ne sais pas comment il prend en compte le dernier enregistrement de Y octets.

Comme dit plus haut, je ne remets pas l'enregistrement de Y octets à la fin de mes fichiers. Donc, je ne sais pas distinguer à l'ouverture un fichier original d'un fichier que j'ai complété.

En tout état de cause, dans mon cas précis, la mise en œuvre de cette dernière méthode est plus compliquée que celle utilisant TFileStream.

Mais je garde les deux sous le coude car elles sont intéressantes.

Cordialement.

Pierre
ChPr est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2010, 16h01   #9
Membre éclairé
 
Homme
Inscription : janvier 2010
Messages : 192
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 39
Localisation : France, Gironde (Aquitaine)

Informations forums :
Inscription : janvier 2010
Messages : 192
Points : 365
Points : 365
Les fichiers définis pas 'file of TRecord' ne peuvent contenir que des TRecord.

Les TFileStream sont en réalité des flux d'octets on peut donc y lire et écrire des 'objets' de tailles différentes. En contrepartie à chaque lecture ou écriture il faut spécifier la taille de ce que l'on veut lire ou écrire. On peut obtenir le même comportement en utilisant un 'file of byte' et les procédure BlocRead et BlockWrite.
batyann811 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 08/02/2010, 16h01   #10
Membre émérite
 
Avatar de Dr.Who
 
Inscription : septembre 2009
Messages : 825
Détails du profil
Informations personnelles :
Âge : 33

Informations forums :
Inscription : septembre 2009
Messages : 825
Points : 905
Points : 905
le problème des file of type c'est justement qu'on ne peut mettre QUE des données du type definis ou de taille condordante.

exemple :
avec un File of TPoint, on peut lire un TSize, avec un File of TRect on peu lire un TPoint.
mais pas l'inverse, lire un TRect dans un file of TPoint risque de poser quelques problèmes en fin de fichier si le nombre de point est impair.

le Stream est plus polyvalent, on peut lire/ecrire ce que l'on veux dedans, stream est à peu prés équivalent à un type File (fichier non typé) sans les problèmes qu'il peut engendré.

sinon, quand je definit un format brut de donnée, je m'arrange toujours pour stocker quelques infos en début de fichier.
signature du fichier, nombre de données, taille de ces derniere, header, footer, table de verification, compréssion, offset etc.

ici, tu peux te contenter d'une structure, comme dans l'exemple :

[count LongWord][theorical size LongWord][date undefined]

ce qui donne :
Code :
1
2
3
4
5
6
7
Read/Write( count, 4 );
Read/Write( Size, 4 );
test Size= Stream.Size -> continue/stop
Read/Write( datas, Size );
ou
boucle N 0 -> Count-1
  Read/Write( data, SizeOf(Data) );
c'est quand même beaucoup plus simple
__________________
[ Sources et programmes de Dr.Who | FAQ Delphi | FAQ Pascal | Règlement | Contactez l'équipe ]
Ma messagerie n'est pas la succursale du forum... merci!
Dr.Who est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +1. Il est actuellement 04h35.


 
 
 
 
Partenaires

Hébergement Web