cs_Jean_Jean
Messages postés615Date d'inscriptiondimanche 13 août 2006StatutMembreDernière intervention13 décembre 2018
-
29 avril 2012 à 10:36
cs_Jean_Jean
Messages postés615Date d'inscriptiondimanche 13 août 2006StatutMembreDernière intervention13 décembre 2018
-
1 mai 2012 à 17:27
Bonjour
J'ai un souci avec la détection d'une Fin de lecture de fichier dans un Thread:
1. Code qui marche :
Je détecte la Fin du parcours de Fichier avec le compteur Interne
procedure TMyThread4.Execute;
var
F : TextFile;
L : String;
FinTrait : Boolean;
begin
{initialisations locales}
...
FinTrait := False;
FMessage := 'Traitement Long en cours...';
Synchronize(AfficherMessage);
{DEBUT TRAITEMENT LONG}
{1. Transfert du Fichier dans une TList...}
...
Try
AssignFile(F,FicTest);
Reset(F);
While Not FinTrait and Not Terminated do
begin
Read(F,L);
Inc(FCount);
ListLignesFic.Add(L);
...
Synchronize(AfficherProgression);
if FCount > FMaxCount then FinTrait := True;
end;
...
FMsgLog := ' - Fichier Trié';
Synchronize(AffichageMemoLog);
Finally
CloseFile(F);
End;
end;
2. Code qui ne marche pas
Détection classique de Fin de fichier par EOF(F) en remplacement du Booléen précédent Fin Trait
procedure TMyThread4.Execute;
var
F : TextFile;
L : String;
begin
{initialisations locales}
...
FMessage := 'Traitement Long en cours...';
Synchronize(AfficherMessage);
{DEBUT TRAITEMENT LONG}
{1. Transfert du Fichier dans une TList...}
...
Try
AssignFile(F,FicTest);
Reset(F);
While Not EOF(F) and Not Terminated do
begin
Read(F,L);
Inc(FCount);
ListLignesFic.Add(L);
...
Synchronize(AfficherProgression);
end;
...
FMsgLog := ' - Fichier Trié';
Synchronize(AffichageMemoLog);
Finally
CloseFile(F);
End;
end;
Le Thread continue sa progression sur Inc(FCount) et ne s'arrête jamais.
J'ai donc l'impression que le EOF n'est pas pris en compte par le Thread Créé.
Question:
1. Dans ce cas, comment se prémunir d'une éventuelle erreur de lecture au delà de la fin de fichier.
Ce qui est bizarre, c'est que mon compteur continue bien au-delà de la valeur du fichier mais ne produit pas d'erreur
2. Ma préférence serait de mettre ma boucle de lecture de Fichier dans la Fiche et d'envoyer au thread, les variables dont il a besoin pour l'affichage. mais je ne sais pas si c'est valable ...
Je progresse mais pas facile à maitriser ces threads... Merci pour vos éclairages.
cs_yanb
Messages postés271Date d'inscriptionlundi 27 octobre 2003StatutMembreDernière intervention 7 juillet 202214 1 mai 2012 à 12:55
Salut,
l'utilisation de Read et de string dans un fichier texte même en utilisant SetLineBreakStyle est.......en gros tu rentres dans un fichier qui ne te donnera jamais de marqueur de fin,donc tu rentres dans une boucle infinie ! Readln te permet d'avoir des marqueurs de fin correcte et de ne pas rentrer dans cette boucle...remplacer string par char permet de faire ce que tu veux,mais caractère par caractère et donc d'arriver à la fin du fichier,mais en terme de performance c'est vraiment pas top...
Pour te convaincre voici une boucle infinie avec Read et un fichier texte de 2 lignes :
procedure TForm1.Button1Click(Sender: TObject);
var
F : TextFile;
S : string;
begin
AssignFile(F,ExtractFilePath(Application.ExeName)+'Test.txt');
Reset(F);
while not eof(F) do
begin
Read(F,S);
ListBox1.Items.Add(S);
end;
CloseFile(F);
ShowMessage('Fin fichier');
end;
Moi je ferais comme cirec en utilisant les streams...
Bon courage @+yanb
Vous n’avez pas trouvé la réponse que vous recherchez ?
cs_Jean_Jean
Messages postés615Date d'inscriptiondimanche 13 août 2006StatutMembreDernière intervention13 décembre 20183 30 avril 2012 à 14:17
Salut yanb,
Merci de m'avoir répondu.
Non Readln ne change rien, d'ailleurs avec un Fichier texte, il vaut mieux utiliser readln...
Je pense que le problème vient du fait que les procédures et méthodes de la VCL sont en réalité incluses dans le Thread principal de l'application...
D'où mon intérêt supplémentaire pour essayer de mettre la boucle princiale dans une procédure de la Fiche... Mais c'est une autre structure que celle que je met ici dans ce post...
En attendant, je peux gérer le parcours de mon fichier dans le exécute du Thread par un boolean.
... Je vous tiens au courant... J'attends de résoudre ce problème pour publier mon code...
Beaucoup d'exemples fictifs de thread sur les sites mais peu de réels applis même simplifiées...
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 1 mai 2012 à 15:35
@yanb:
oui on le sait que c'est très long ... mais le but de cette "procédure" c'est justement d'avoir une procédure longue afin de faire une démo concrète de l'utilisation d'un Thread (cf. son code):
" FMessage := 'Traitement Long en cours...';"
cs_Jean_Jean
Messages postés615Date d'inscriptiondimanche 13 août 2006StatutMembreDernière intervention13 décembre 20183 1 mai 2012 à 17:27
re bonjour,
Merci pour vos commentaires. Je réponds dans l'ordre.
1. Effectivement, ça marche avec un type Char. Mais pour la démo, j'utilisai un TextFile car ça me paraissait plus rapide de ligne par ligne... Comme quoi!
2. Dans un Fichier Texte, mieux vaut Utiliser Readln effectivement et je suis d'acord que les performances ne sont pas au rendez-vous...
3. Les Stream sont la solution. Commme je vais avoir de nombreux fichiers à analyser dont certains seront assez volumineux, j'ai développé une structure particulière pour mes besoins.
Méthode que je pense adopter :
1. J'ouvre le fichier de travail avec un FileStream 2. Je le copie par bloc dans un memoryStream
(dans le code ci-dessous, un bloc = 1 ligne du fichier)
3. Je procède aux vérifications (ici test de longueur), comptabilité des erreurs constatées et
affichage des progressions et messages
4. Je créée une image du fichier dans un TList afin
pour l'exemple de le trié par ordre alphabétique rapidement
Voilà où j'en suis. ça ne parait pas pas très optimisé. Je vais devoir choisir entre le mémoryStream et la TList me semble t-il. Utiliser les deux parait surfait...
Voici le bout de code actuel:
var
FS : TFileStream;
MSb : TMemoryStream;
I : LongInt;
fFCount : Real; // Pour séparation des milliers dans Format
L,M : String;
C : Char;
TailleBloc: Integer;
Ligne : array [1..12] of char;
begin
{initialisations locales}
...
{DEBUT TRAITEMENT LONG}
{1. Transfert des lignes du Fichier dans une TList afin de trier rapidement
les valeurs du fichier d'origine par ordre alphabétique croissant}
FS := TFileStream.Create(FicTest, fmOpenRead );
TailleBloc := 12;
L := '';
C := #0;
For I:=1 to FS.Size div TailleBloc do
Begin
MSb := TMemoryStream.Create; // Création bloc
MSb.CopyFrom(FS,TailleBloc); // Copie d'un bloc
MSb.Position := 0; // Index début de Bloc
MSb.Read(Ligne,12);
L := Ligne;
If not ((Ligne[11] = #13 ) and (Ligne[12] = #10)) then
begin
inc(FError);
FMsgLog := ' - er n°'+InttoStr(FError)+' : '+L;
Synchronize(AffichageMemoLog);
end;
ListLignesFic.Add(L);
Inc(FCount);
end;
FS.Free;
ListLignesFic.Sort;
fFCount := FCount;
FMsgLog := ' - '+Format('%.0n',[fFCount/1])+' éléments triés';
Synchronize(AffichageMemoLog);
FMessage := 'Triage du Fichier effectué...';
Synchronize(AfficherMessage);
...
if FError = 0 then
begin
FMsgLog := 'Vérification longueur des '+inttoStr(FCount)+' enregistrements effectuée';
Synchronize(AffichageMemoLog);
FMsgLog := '- Aucune erreur détectée';
Synchronize(AffichageMemoLog);
end;