Problème avec BlockRead/BlockWrite

Signaler
Messages postés
4
Date d'inscription
samedi 29 mars 2003
Statut
Membre
Dernière intervention
4 juillet 2006
-
Messages postés
220
Date d'inscription
lundi 30 octobre 2000
Statut
Membre
Dernière intervention
15 juillet 2013
-
Bonjour,

J'ai un problème avec BlockRead/BlockWrite :

L'objectif est de créer un petit programme qui gère des enregistrements d'élèves, de matière, de notes et de classe. Ces informations sont stockées sur un unique fichier binaire contenant des index sur deux niveau (le premier index pointe sur les différent indexes de second niveau, ces dernier pointant sur les différent enregistrements).

Je n'arrive pas à écrire puis à lire correctement les informations que j'écris sur le fichier : J'arrive à écrire puis lire quelques 'enregistrements' (ou 'structures') lorsque ces derniers sont de même type. Cependant dès que je combine des 'enregistrements' de différente taille/type, à la lecture j'obtiens des données aléatoire.

D'avance merci beaucoup et bonnes fêtes de fin d'année!!!


En résumé :
Ce code marche :
    // IndexMatiere, IndexEleve, IndexClasse sont de type LongInt      
    BlockWrite(Fichier, IndexMatiere, SizeOf(IndexMatiere));
    BlockWrite(Fichier, IndexEleve, SizeOf(IndexEleve));
    BlockWrite(Fichier, IndexClasse, SizeOf(IndexClasse));  
    //Puis : 
    BlockRead(Fichier, IndexMatiere, SizeOf(IndexMatiere));
    BlockRead(Fichier, IndexEleve, SizeOf(IndexEleve));
    BlockRead(Fichier, IndexClasse, SizeOf(IndexClasse));


Mais pas celui la :
   // EnTete est un enregistrement
    // IndexMatiere, IndexEleve, IndexClasse sont de type LongInt      
    BlockWrite (Fichier,EnTete,SizeOf(EnTete),TailleLu);
    BlockWrite(Fichier, IndexMatiere, SizeOf(IndexMatiere));
    BlockWrite(Fichier, IndexEleve, SizeOf(IndexEleve));
    BlockWrite(Fichier, IndexClasse, SizeOf(IndexClasse));  
    //Puis : 
    BlockRead(Fichier,EnTete,SizeOf(EnTete),TailleLu);
    BlockRead(Fichier, IndexMatiere, SizeOf(IndexMatiere));
    BlockRead(Fichier, IndexEleve, SizeOf(IndexEleve));
    BlockRead(Fichier, IndexClasse, SizeOf(IndexClasse));


Le code utilisé est (les fonctions appellées sont 'ChargeIndex(FichierEcole)' Puis 'EnregistreIndex(FichierEcole)'):
unit GestionFichiers;
{$IOCHECKS ON ($I+}
interface
  uses Main;{Fonctions Globales}
  Function EcritClasse(Classe:TClasse):boolean;
  Function OuvrirFich():boolean;
  Function FermerFich():boolean;
{Enregistrements Globaux}
Type TEnTete = record
  Taille : integer; //Taille du bloc
  TypeEng : integer; {1: Classe}
End;
{Variables globales}
Var
  FichierEcole:File;    //Fichier contenant les données à stocker sur le disque dur
  CurrDir:String;       //Stock le chemin du répertoire courant
{Constantes globales}
Const
  NomFichEcole='FichierEcole.dat'; //Stock le nom du fihier
  TailleIndex=100;

implementation

uses
  SysUtils,GestionIndex;{Fonctions Locales}
{--------------------------------------------------------------------------------------------------
                                Test si un fichier existe
--------------------------------------------------------------------------------------------------}
Function TestSiExiste(NomFich:string;Chemin:string):boolean;
Var
  Fichier:file; //Fichier dont on doit tester l'existance
Begin
  {$I-}
    AssignFile (Fichier, Chemin+NomFich);
    FileMode := 0; //Accès en lecture seule
    Reset(Fichier);
    CloseFile(Fichier);
  {$I+}
  Result:=(IOResult=0)and(NomFich<>'')and(Chemin<>'');
End;

{--------------------------------------------------------------------------------------------------
                              Cree un fichier binaire 
--------------------------------------------------------------------------------------------------}
Function CreerFichier(NomFich:string;Chemin:string):boolean;
Var
  Fichier:file; //Fichier que l'on doit créer
Begin
  {$I-}
    AssignFile (Fichier, Chemin+NomFich);
    Rewrite(Fichier);
    CreerIndex;                //Création de l'index
    EnregistreIndex(Fichier);  //et écriture de ce dernier sur le fichier
    CloseFile(Fichier);
  {$I+}
  Result:=(IOResult=0)and(NomFich<>'')and(Chemin<>'');
End;

{--------------------------------------------------------------------------------------------------
                                 Ouverture du fichier
--------------------------------------------------------------------------------------------------}
Function OuvrirFich():boolean;
Begin
  Result:=True;

  //On extrait le chemin du repertoire en cour
  If Length(CurrDir)=0 then CurrDir:=GetCurrentDir+'\';

  //On test si le fichier existe et au besoin on essait de le créer
  If not TestSiExiste(NomFichEcole,CurrDir) Then Begin
    Writeln('Le fichier d''enregistrement des donnees n''existe pas, il va etre creer.');
    If CreerFichier(NomFichEcole,CurrDir) Then Begin
    //Contiendra le code qui enregistrera les données en mémoire...
    End Else Begin
      Writeln('Impossible de creer le fichier d''enregistrement des donnees.');
      Result:=False;
    End;
  End;
  If Result Then Begin
    {$I-}
      AssignFile (FichierEcole, NomFichEcole);
      FileMode:=2;   //Ouverture en lecture-écriture
      Reset(FichierEcole,1);//Ouvre le fichier avec le mode FileMode et une taille de 1
    {$I+}
    If IOResult<>0 then begin
      Writeln ('Impossible d''ouvrir le fichier.');
      Result:=false;
    End Else Result:=True;
  End;
End;

{--------------------------------------------------------------------------------------------------
                                 Fermeture du fichier
--------------------------------------------------------------------------------------------------}
Function FermerFich():boolean;
Begin
  {$I-}
    CloseFile(FichierEcole);
  {$I+}
  If IOResult<>0 Then Begin
    Writeln('Impossible de fermer le fichier.');
    Result:=False;
  End Else Result:=True;
End;


unit GestionIndex;
interface
  uses GestionFichiers;{Fonctions Globales}
  Function CreerIndex():boolean;
  Function EnregistreIndex(Var Fichier:File):boolean;
  Function ChargeIndex(Var Fichier:File):boolean;
{Enregistrements Globaux}
Type TIndexSecondaire = record
  Clef : Integer;
  AdresseDeb : LongInt;
  Taille : Integer;
End;

Type TIndex = record
  IndexMatiere,IndexEleve,IndexClasse : LongInt;//Pointe vers les index secondaire
  Matiere,Eleve,Classe:array[1..TailleIndex]of TIndexSecondaire;//Pointe vers les enregistrements
End;{Variables globales}
Var
  Index:TIndex;

implementation

Uses
  Main,GestionEnregistrements,SysUtils,Classes;{Fonctions Locales}
{--------------------------------------------------------------------------------------------------
                           Chargement en mémoire de l'index
--------------------------------------------------------------------------------------------------}
Function ChargeIndex(Var Fichier:File):boolean;
Var
  TailleLu:Integer;
  EnTete: TEnTete;
  i:integer;
Begin
  TailleLu:=0;
  If OuvrirFich Then Begin;  //On ouvre le fichier
    BlockRead(Fichier,EnTete,SizeOf(EnTete),TailleLu);
    With Index do Begin
      BlockRead(Fichier, IndexMatiere, SizeOf(IndexMatiere));
      BlockRead(Fichier, IndexEleve, SizeOf(IndexEleve));
      BlockRead(Fichier, IndexClasse, SizeOf(IndexClasse));
      For i:=1 to TailleIndex do Begin
        BlockRead(Fichier, Matiere[i], SizeOf(Matiere[i]));
        BlockRead(Fichier, Eleve[i], SizeOf(Eleve[i]));
        BlockRead(Fichier, Classe[i], SizeOf(Classe[i]));
      End;
    End;
    Result:=(FermerFich) and (TailleLu<>0)
  End Else Result:=False;
End;

{--------------------------------------------------------------------------------------------------
                           Ecriture de l'index sur le fichier
--------------------------------------------------------------------------------------------------}
Function EnregistreIndex(Var Fichier:File):boolean;
Var
  TailleEcrit:Integer;
  EnTete: TEnTete;
  i:integer; //variable de boucle
Begin
  TailleEcrit:=0;
  EnTete.Taille:=SizeOf(Index);
  EnTete.TypeEng:=0;
  If OuvrirFich Then Begin;  //On ouvre le fichier
    BlockWrite(Fichier, EnTete, SizeOf(EnTete), TailleEcrit);  //On écrit l'entête
    //On est obligé d'écrir l'index par morceau car autrement
    //on déclanche une erreur: buffer overflow(Erreur E/S 1784)
    With Index do Begin
      BlockWrite(Fichier, IndexMatiere, SizeOf(IndexMatiere));
      BlockWrite(Fichier, IndexEleve, SizeOf(IndexEleve));
      BlockWrite(Fichier, IndexClasse, SizeOf(IndexClasse));
      For i:=1 to TailleIndex do Begin
        BlockWrite(Fichier, Matiere[i], SizeOf(Matiere[i]));
        BlockWrite(Fichier, Eleve[i], SizeOf(Eleve[i]));
        BlockWrite(Fichier, Classe[i], SizeOf(Classe[i]));
      End;
    End;
    Result:=(FermerFich) and (TailleEcrit<>0) and (TailleEcrit=SizeOf(Index))
  End Else Result:=False;
End;

1 réponse

Messages postés
220
Date d'inscription
lundi 30 octobre 2000
Statut
Membre
Dernière intervention
15 juillet 2013

Salut,
*****
Petite parenthèse, dans l'unité SysUtils, il existe déjà une fonction nommé 'FileExists' :

function FileExists(const FileName: string): Boolean;
Description :
La fonction FileExists renvoie True si le fichier FileName existe. Dans le cas contraire, FileExists renvoie False.
Donc au lieu de mettre :
TestSiExiste(NomFichEcole,CurrDir)
tu peut mettre :
FileExists(CurrDir+NomFichEcole)

Et LongInt et Integer sont les même type 32 bits signé
*****
Pour le reste, je n'ai pas de réponses qui me viennent comme ça mais as-tu regardé dans le fichier 'FichierEcole.dat' avec un éditeur hexadécimal par exemple ou même le bloc note pour voir si tout était en ordre après l'enregistrement?
En clair :
il doit contenir :
4 octets pour 'EnTete.Taille'
4 octets pour 'EnTete.TypeEng'

4 octets pour 'IndexMatiere'
4 octets pour 'IndexEleve'
4 octets pour 'IndexClasse'

et 'TailleIndex' fois
4 octets pour Matiere[i]
4 octets pour Eleve[i]
4 octets pour Classe[i]

soit une taille total sur le disque de 'TailleIndex'*12+20

Si c'est le cas, c'est lors de la lecture que ça merde, sinon, c'est pendant l'écriture et là, c'est normal que la lecture soit fausse.