begin process at 2010 02 10 10:49:26
  Trouver un code source :
 
dans
 
Accueil > Forum > 

Archive Delphi

 > 

Archives

 > 

Fichier / Disque

 > 

Comment faire un fichier avec plusieurs types ?


Derniers messages déposésPoser une question dans le forum ou lancer une discussion

Comment faire un fichier avec plusieurs types ?

lundi 13 mars 2006 à 16:54:53 | Comment faire un fichier avec plusieurs types ?

mkolivier

Membre Club

Bonjour,

Je souhaiterai faire un fichier avec plusieurs types. Par exemple :

type TEnteteFichier = record
 Version: integer;
 ExtensionFichier: string[10];
 f: file;
end;

type TLignefichier = record
 Nom: string[50];
 Prenom: string[100];
 Age: integer;
end;

procdure Enregistrer();
var
 Head: TEnteteFichier;
 Ligne: TLignefichier;
begin
 Head.Version := 3;
 Head.ExtensionFichier := '.abc';

 Ligne.Nom := 'Durand';
 Ligne.Prenom := 'Jean';
 Ligne.Age := 30;

 AssignFile(f, 'c:\test.dat');
 Rewrite(f);
 Write(f, Head);
 Write(f, Ligne);
 Closefile(f);
end;

mais ca ne marche pas ... quelqu'un peut me dire comment faire ?

Merci

Olivier

lundi 13 mars 2006 à 19:58:35 | Re : Comment faire un fichier avec plusieurs types ?

cirec

Membre Club Administrateur CodeS-SourceS
Salut,

Bon éclaire moi déjà sur ces deux points en rouge, je pense que ton problème vient de là

type TEnteteFichier = record
 Version: integer;
 ExtensionFichier: string[10]; // 4 aurait suffit et 100 pour un prénom ça beaucoup aussi mais bon c'est ton choix
 f: file;                                 // c'est pour quoi ça ?
end;
AssignFile(f, 'c:\test.dat');      // et ici de quel type est F ?


@+
Cirec
mardi 14 mars 2006 à 03:45:15 | Re : Comment faire un fichier avec plusieurs types ?

f0xi

Membre Club Administrateur CodeS-SourceS
Réponse acceptée !
n'oublis pas de regarder les codes sources :

http://www.delphifr.com/codes/CREER-TYPE-FICHIER-GESTION-DECOULLE_36520.aspx


un conseil, quand tu ecris un type enregistrement (record) n'oublis pas de faire la fonction qui vas bien avec, ici pour tes deux exemples :

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

  // permet la conversion rapide du code version (integer) en quatre chiffre
  // distinct : version M.m.r.b

  TABCVersion = record
     case integer of
       0: (Code : integer);
       1: (Major, Minor, Release, Build : byte);
  end;

  // permet de stocker le Header (entete) du fichier.
  // on y retrouve le code version (integer) et l'extention (string[4])
  TABCHeader = record
    Version   : integer;
    Extention : string[4];
  end;
  // type file du header, en effet, pour chaque partie de fichier on la considere
  // comme un fichier elle meme.
  FileHeader = file of TABCHeader;

  // permet de stocker les informations dans notre fichier
  // on y retrouve nom et prenom (string[20]) et l'age (unsigned 8bits)
  // 0 a 255 bien suffisant pour stocker un age.
  TABCData = record
    Name,Surname : string[20];
    Age          : Byte;
  end;
  // comme pour le header, le type fichier de notre type de donnée
  FileData = file of TABCData;
  // comme on risque de devoir traiter de nombreuses données,
  // on crée un tableau dynamique pour les stocker toutes.
  TABCDataArray = array of TABCData;

  // cette structure vas nous faciliter la manipulation des fichiers
  // et de faire un tout entre le Header et les données.
  TABCStruct = record
    Header : TABCHeader;
    Datas  : TABCDataArray;
  end;

  // permet de definir rapidement un enregistrment TABCVersion
  function ABCVersion(const Ver : LongWord) : TABCVersion; overload;
  function ABCVersion(const Ma,Mi,Re,Bu : byte) : TABCVersion; overload;

  // permet de definir rapidement un enregistrement TABCHeader
  function ABCHeader(const Ver : LongWord; const Ext : string) : TABCHeader; overload;
  function ABCHeader(const Ver : TABCVersion; const Ext : string) : TABCHeader; overload;

  // permet de definir rapidement un enregistrement TABCData
  function ABCData(const N,S : string; const A : byte) : TABCData;

  // permet de Pusher les données dans un tableau dynamique, sans ce soucier
  // de l'affectation de taille... dynamique jusqu'au bout donc.
  procedure ArrayPush(var ArDt : TABCDataArray; const Dt : TABCData);
  // vide un tableau dynamique.
  procedure ArrayFlush(var ArDt : TABCDataArray);

  // nous permet de lire le fichier
  procedure ReadFile(const FileName : string; var Dts : TABCStruct);
  // nous permet d'ecrire le fichier
  procedure WriteFile(const FileName : string; const Dts : TABCStruct);

var
  Form1: TForm1;

implementation

{$R *.dfm}

function ABCVersion(const Ver : LongWord) : TABCVersion;
begin
  result.Code := Ver;
end;

function ABCVersion(const Ma,Mi,Re,Bu : byte) : TABCVersion;
begin
  result.Major  := Ma;
  result.Minor  := Mi;
  result.Release:= Re;
  result.Build  := Bu;
end;

function ABCHeader(const Ver : LongWord; const Ext : string) : TABCHeader;
begin
  Result.Version   := Ver;
  Result.Extention := Ext;
end;

function ABCHeader(const Ver : TABCVersion; const Ext : string) : TABCHeader;
begin
  Result.Version   := Ver.Code;
  Result.Extention := Ext;
end;

function ABCData(const N,S : string; const A : byte) : TABCData;
begin
  Result.Name    := N;
  Result.Surname := S;
  Result.Age     := A;
end;

procedure ArrayPush(var ArDt : TABCDataArray; const Dt : TABCData);
begin
  // c'est ici que la magie opere.
  // on redefinit la taille du tableau a length+1
  SetLength(ArDt,length(ArDt)+1);
  // et on place la donnée a la fin
  ArDt[High(ArDt)] := Dt;
end;

procedure ArrayFlush(var ArDt : TABCDataArray);
begin
  SetLength(ArDt,0);
end;

procedure ReadFile(const FileName : string; var Dts : TABCStruct);
var Fh : FileHeader;
    Fd : FileData;
    D  : TABCData;
begin
  // si le fichier existe on peu lire
  if fileexists(filename) then begin
     // deux structure differente, deux block try
     try
       // d'abord le header
       AssignFile(Fh,FileName);
       Reset(Fh);
       Read(Fh,Dts.Header);
     finally
       CloseFile(Fh);
     end;

     Try
       // ensuite les données
       AssignFile(Fd,FileName);
       Reset(Fd);
       // on oublis pas de sauter le header du fichier
       Seek(Fd,SizeOf(TABCHeader));
       // tant qu'on est pas a la fin du fichier
       while not EOF(Fd) do begin
          // on lit
          Read(Fd,D);
          // on Push
          ArrayPush(Dts.Datas,D);
       end;
     finally
       CloseFile(Fd);
     end;
  end;
end;

procedure WriteFile(const FileName : string; const Dts : TABCStruct);
var Fh : FileHeader;
    Fd : FileData;
    N  : integer;
begin
  // cette condition empeche l'ecrasement du fichier
  // et egalement d'enregistrer un fichier vide
  if (not fileexists(filename)) and (high(Dts.Datas) <> -1) then begin
     try
       // comme pour la lecture, on commence d'abord par le Header
       AssignFile(Fh,FileName);
       // ici Rewrite pour créer le fichier
       Rewrite(Fh);
       Write(Fh,
Dts.Header);
     finally
       CloseFile(Fh);
     end;
    
     // et enfin les données 
     try
       AssignFile(Fd,FileName);
       // attention on ne Rewrite (C) pas ici, on Reset (ouverture en R/W).
       Reset(Fd);
       // on oublis pas de sauter le header pour ne pas ecrire dessus.
       Seek(Fd,SizeOf(TABCHeader));
       // on init notre compteur a 0
       N := 0;
       // tant que N est inferieur ou egale a l'index du dernier element.
       // on aurait egalement pus ecrire :
       // while N < Length(Dts.Datas) do ... c'est kif kif
       while N <= high(Dts.Datas) do begin
          // on ecrit la donnée N
          Write(Fd,
Dts.Datas[N]);
          // on oublis pas d'incrementer le compteur
          Inc(N);
       end;
     finally
       CloseFile(Fd);
     end;
  end;
end;

// ici on vas tester tout cela
procedure TForm1.FormCreate(Sender: TObject);
var
    // permet la conversion Code version integer vers 4 chiffre (byte)
    Version : TABCVersion;
    // permet de tester : Fichier1 en ecriture et Fichier2 en lecture
    Fichier1,Fichier2 : TABCStruct;
    // permet de manipuler les données
    FData   : TABCData;
    // toujours utile
    N       : integer;
    // permet d'effacer le fichier de test, pas besoin de lui donner un type.
    FE      : file;
begin

  // on definit la version de test
  Version         := ABCVersion(1,2,4,8);
  // on place nos infos dans la structure
  Fichier1.Header := ABCHeader(Version,'abc');
  // on genere des données aleatoire de test et on les push dans le tableau
  // de la structure, bizarement, la completion de code ne "vois" pas
  // .Datas dans la structure ... etrange. pourtant aucune erreurs.
  for N := 0 to 19 do
      ArrayPush(Fichier1.Datas, ABCData('testN'+IntToStr(N),'testS'+IntToStr(N),N));

  // on affiche la version
  Listbox1.Items.Add(format('Version   : h%.4x',[Fichier1.Header.Version]));
  // puis l'extention
  Listbox1.Items.Add(format('Extention : %s',[Fichier1.Header.Extention]));
  // et enfin les données
  for N := 0 to High(Fichier1.Datas) do begin
      FData := Fichier1.Datas[N];
      listbox1.Items.Add(format('%s %s %d',[FData.Name,FData.Surname,FData.Age]));
  end;
  // on saute une ligne
  listbox1.Items.Add('');

  // on tente d'ecrire le fichier (fichier1)
  WriteFile('c:\testfile.dts',Fichier1);
  // puis de le lire (fichier2)
  ReadFile('c:\testfile.dts',Fichier2);

  // on affiche le resultat de fichier2, version, extention, données
  Listbox1.Items.Add(format('Version   : h%.4x',[Fichier2.Header.Version]));
  Listbox1.Items.Add(format('Extention : %s',[Fichier2.Header.Extention]));
  for N := 0 to High(Fichier2.Datas) do begin
      FData := Fichier2.Datas[N];
     listbox1.Items.Add(format('%s %s %d',[FData.Name,FData.Surname,FData.Age]));
  end;
 
  // enfin on efface le fichier de test, si il existe ... on sais jamais
  if fileexists(
'c:\testfile.dts') then begin
     AssignFile(FE,'c:\testfile.dts');
     // pas besoin de l'ouvrir
     Erase(FE);
     // pas besoin de le fermer
  end;
end;

end.


et voila, j'espere que cela t'aideras.


La theorie c'est quand on sait tout, mais que rien ne fonctionne.
La pratique c'est quand tout fonctionne, mais que personne ne sait pourquoi.

mardi 14 mars 2006 à 04:08:40 | Re : Comment faire un fichier avec plusieurs types ?

f0xi

Membre Club Administrateur CodeS-SourceS
rhaaa ... je viens de me rendre compte qu'encore une fois j'ai fait tout le boulot :

et pourtant je dis bien au debut :

"un conseil, quand tu ecris un type enregistrement (record) n'oublis pas de faire la fonction qui vas bien avec, ici pour tes deux exemples :"



et paf je pond tout le programme ... lol
faut que j'arrete.



La theorie c'est quand on sait tout, mais que rien ne fonctionne.
La pratique c'est quand tout fonctionne, mais que personne ne sait pourquoi.

mardi 14 mars 2006 à 08:14:01 | Re : Comment faire un fichier avec plusieurs types ?

Kenavo

Réponse acceptée !
Salut,

En supposant que tu voulais écrire :

type TEnteteFichier = record
 Version: integer;
 ExtensionFichier: string[10];
end;

type TLignefichier = record
 Nom: string[50];
 Prenom: string[100];
 Age: integer;
end;

var
  f : File;


Je dirais qu'il y a plusieurs réponses :

Si le fichier est constitué alternativement de TEnteteFichier et de TLigneFichier, il faut créer un type
type TEnregitrement = record
  Entete : TEntetFichier;
  Ligne : TLigneFichier;
end;

et
var
  Data :
TEnregistrement;
  f    : file of TEnregistrement;

procedure Enregistrer;
var
 Head: TEnteteFichier;
 Ligne: TLignefichier;

begin
 with Data do
 begin 
   Head.Version := 3;
   Head.ExtensionFichier := '.abc';

   Ligne.Nom := 'Durand';
   Ligne.Prenom := 'Jean';
   Ligne.Age := 30;

 end;
 AssignFile(f, 'c:\test.dat'); 
 Rewrite(f);
 Write(f, Data);
 Closefile(f);
end;

 

Si le fichier est constitué d'un seul
TEnteteFichier suivi d'un nombre inconnu de TLigneFichier, tu peux utiliser (comme tu le fais) un fichier non typé, mais alors, il faut savoir lui causer ! Avec BlockWrite et BlockRead

 AssignFile(f, 'c:\test.dat');
 Rewrite(f,1);
 BlockWrite(f, Head, sizeof(Head),n);  // n : integer
 BlockWrite(f, Ligne, sizeof(Ligne),n);
 BlockWrite(f, Ligne2, sizeof(Ligne),n);
 BlockWrite(f, Ligne3, sizeof(Ligne),n);
 BlockWrite(f, Ligne4, sizeof(Ligne),n);
 Closefile(f);

et pour lire :

 AssignFile(f, 'c:\test.dat');
 Reset(f,1);
 BlockRead(f, Head, sizeof(Head),n);
 BlockRead(f, Ligne, sizeof(Ligne),n);
 
BlockRead(f, Ligne1, sizeof(Ligne),n);
 BlockRead(f, Ligne2, sizeof(Ligne),n);
 BlockRead(f, Ligne3, sizeof(Ligne),n);
 BlockRead(f, Ligne4, sizeof(Ligne),n);
 
Closefile(f);

Si tu n'as, dans ton fichier, qu'un TEnteteFichier suivi d'un seul TLigneFichier, les deux méthodes sont applicables !


Ken@vo

Code, Code, Codec !

jeudi 16 mars 2006 à 22:12:16 | Re : Comment faire un fichier avec plusieurs types ?

mkolivier

Membre Club
Merci pour vos réponses, j'ai juste une question : pourquoi les fichiers générés sont si lourd ? car si je prends l'exemple de Kenavo, le fichier test.dat fait 80 ko c'est énorme pour ce qu'il y a dedans !!!

jeudi 16 mars 2006 à 23:03:17 | Re : Comment faire un fichier avec plusieurs types ?

mkolivier

Membre Club
Désolé je reviens ici en fait c'est ok, c'est marrant (je suis encore débutant), je n'avais pas vu qu'en mettant Rewrite(f, 1) ou Rewrite (f), le résultat est différent, le fichier est beaucoup moins lours en mettant le 1 en paramètre. Par contre le "1" cela signifie quoi ?

Merci

Olivier
vendredi 17 mars 2006 à 00:19:06 | Re : Comment faire un fichier avec plusieurs types ?

cirec

Membre Club Administrateur CodeS-SourceS
Salut,

si tu veux gagner de la place c'est ici que ça se passe:

type TEnteteFichier = record
 Version: integer;              // 4 Octets
 ExtensionFichier: string[10];  // 10 + 1 = 11 Octets 
end;

type TLignefichier = record
 Nom: string[50];               // 50 + 1 = 51 Octets
 Prenom: string[100];           // 101 Octets
 Age: integer;                  // 4 Octets;
end

Ce qui nous fait 15 Octets pour l'entête et 156 par Ligne ce qui fait 171 Octets pour un fichier avec une entête et une ligne.


type TEnteteFichier = record
 Version: integer;              // Si Version n'est pas plus grand que 255 tu peux utiliser Byte il ne prend que 1 Octet
 ExtensionFichier: string[4];  // 4 + 1 = 5 Octets 
end;

type TLignefichier = record
 Nom: string[20];               // 20 + 1 = 21 Octets avec 15 c'est déjà un chouette nom
 Prenom: string[15];            // 15 + 1 = 16 Octets avec 15 c'est déjà un chouette prénom
 Age: Byte;                    
// 1 Octets; on a rarement vu quelqu'un de plus de 255 ans
end

Ce qui nous fait 6 où 9 Octets pour l'entête en fonction de Byte où Integer et 38 Octets par ligne ce qui fait un fichier de 44 à 47 Octets
Alors bien évidement sur 1 enregistrement c'est déjà remarquable tu peux t'imaginer sur une centaine

Ensuite pour l'histoire de rewrite(f, 1) où rewrite(f) fait un F1 pour comprendre que ce n'est pas ceci qui va influencer sur la taille du fichier


@+
Cirec

vendredi 17 mars 2006 à 08:12:17 | Re : Comment faire un fichier avec plusieurs types ?

Kenavo

Et encore, Cirec tu ne tiens pas compte de l'alignement des données ! Si je je me trompe pas, les données sont alignées sur  8 octets (par défaut par le compilateur de D7) ou 4 octets (par défaut par le compilateur de D4). 
Pour prendre le minimum de place (et pour que le fichier d'enregistrements soit lisible, quelque soit l'alignement) il faut utiliser des Packed Record au lieu de simples record dans les définitions de type. Sinon, un octet (byte) occupe 8 octets, soit autant qu'un int64 ou qu'un double !

Ken@vo

Code, Code, Codec !

vendredi 17 mars 2006 à 10:24:54 | Re : Comment faire un fichier avec plusieurs types ?

cirec

Membre Club Administrateur CodeS-SourceS

Alors la, Kenavo, j'avoue que ça dépasse un peut mes connaissances, tout ce que je sais c'est ce que j'ai testé et quand je donne une taille de 171 Octets j'obtiens 172 Octets avec le compilateur D4 et si j'examine le fichier en hexa je retrouve ce que j'avançais plus haut : 1 Octet pour un Byte, 4 Octets pour un Integer, 11 Octets pour un String[10] : 10 Octets sont présents pour la taille maximale admise pour ce String et 1 Octet est ajouté devant pour la taille réel à lire. Comme je ne trouve pas de grande différence entre mon calcule et la réalité (1 Octet que j'ai mis sur le compte de l'EOF ?)  je me dis que je ne dois pas être loin de la réalité


@+
Cirec

1 2

Cette discussion est classée dans : fichier, ligne, string, head, types


Répondre à ce message

Sujets en rapport avec ce message

NB Ligne dans un fichier texte [ par ProGMaN007 ] salut, comment connaître le nombre de ligne dans un fichier txt ? problèmes de bibliothèques [ par costello ] j'avais cru voir un sujet ou une source à propos de ça, mais j'ai pas pu la retrouver, désolé... et pourtant je dois résoudre ce problème:mon prog mar Fichier typé (RECORD) [ par selma-elec ] UN fichier à été créer sur disque avec borland pascal 7.0 avec des enregistrement de ce type :Type Tata = Record Chemin : integer lancement d'un fichier au démarrage de l'application [ par Pierre ] Comment est-il possible, en Delphi, de lancer un fichier (.txt par exemple comme je l'indique ci-après) au démarrage sans que la TForm apparaisse ? Av Lecture fichier texte ligne par ligne [ par MattXSFR ] J'utilise le code suivant pour copier le contenu d'un fichier texte dans une liste box (une ligne de list box pour chaque ligne du fichier) :procedure Ouverture, lecture d'un fichier en mode binaire [ par SMoG ] YoOOooOOoooooo la dedans :)bon voila, j'aimerais ouvrir et lire un fichier en mode binaire ligne par ligne, mais j'ai trouvé que des méthodes qui lise fichier d'aide en ligne [ par bdv ] quelqu'un a t il déja réalisé une aide en lignequelque soit sa forme toutes idées, suggestions, ou sources bienvenuesthanks Copier un Fichier dans une string [ par lomig ] Question a la con: comment fait-on pour copier un fichier (texte) dans une chaine (string)?? Suppression ligne dans un textfile [ par coframi ] Existe il une autre méthode pour supprimer une ligne dans un fichier texte que celle ci: - recopie des lignes voulues dans un fichier temporaire. Manipulation d'un fichier texte [ par koaiz ] Hug Tribue des Programmeur PalJ'utilise un fichier texte pour mon application comme log file mais j'ai un probleme car lors de la fermeture de l'appli


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,655 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales