broidsy
Messages postés4Date d'inscriptionsamedi 29 mars 2003StatutMembreDernière intervention 4 juillet 2006
-
29 déc. 2004 à 18:13
cs_barbichette
Messages postés220Date d'inscriptionlundi 30 octobre 2000StatutMembreDernière intervention15 juillet 2013
-
30 déc. 2004 à 10:36
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;
cs_barbichette
Messages postés220Date d'inscriptionlundi 30 octobre 2000StatutMembreDernière intervention15 juillet 2013 30 déc. 2004 à 10:36
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.