PDA

Afficher la version complète : problème avec Tcl



Erikr le Rouge
08/07/2008, 16h50
Salut à tous,

j'ai des fichiers textes à traité, qui contiennent plusieurs ligne, contenant chacune deux réel, x et y.
J'ai écris un petit script en tcl qui ouvre le fichier source, le lit et à chaque fois qu'il voit un y négatif, il ajoute 360. Que le script ai ajouté ou non 360, il recopie des données dans un autre fichier.

Mon pb, c'est que sur un petit fichier de test, contenant 6 lignes, il affiche les résultats à l'écran, mais aucun résultats dans le fichier (fichié crée, de taille 0 octets)
sur un fichier de 10.000 lignes il ne les écrit pas toutes (soit 9906 dans le premier cas, soit 9818 "et demie" dans un deuxième cas).

Je ne comprend pas :
pourquoi ça ne fonctionne pas avec un petit fichier ?
pourquoi ça ne fonctionnna pas avec un fichier de 94 lignes ?
pourquoi ça ne fonctione pas avec un fichier de 96 lignes ?
pourquoi il manque des lignes à un fichier de 10.000 lignes ?
pourquoi dans un cas la ligne n'est pas entière ?

Si des progammeurs peuvent m'aider ?? ce ne serait pas une histoire de tampon ou autre ??? Ca fait plus d'une heure trente que je suis dessus, a force d'avoir le nez dans le guidon, j'y vois plus rien...

Please, help !

Pour ceux qui seraient tenté de me dire : écris le en C, perl, python ou autre, c'est sympa, mais je le veux en tcl...

merci d'avance et à +, ci dessous, mon script :

#!/usr/bin/tclsh

#Programme pour transformer un angle négatif en son homologue positif.
#Formule générale : nouvel angle = 360 - |ancien angle|

set path [pwd]
puts "\nWorking path : $path"

puts "\n\t*** Be careful your file ends without blank line ***\n"
set fichier ""
#turlututu juste pour ne pas avoir de pb dans la boucle, un ctrl+c ou un fichier turlututu (improbable) stope le prog.
while {$fichier!="turlututu"} {
puts "\nWhich file ? (ctrl-c to abort)"
set fichier [gets stdin]
set inputfile [open $path/$fichier r]
set rname [file rootname $fichier]
puts "input : $rname"
append rname "_mod360.dat"
puts "output : $rname"
set outputfile [open $path/$rname w]
set line [gets $inputfile]
set finfichier [eof $inputfile]
set i 0
set angle 0

while {$finfichier!=1} {
set angle [lindex $line 1]
puts "line : $line"
switch angle {
"" {
puts "\n ** Error : the last line is a blank line **\n\n\tProgram teminated\n"
set erreur 1
}
default {
puts "angle : $angle ** abs : [expr abs($angle)]"
if {$angle<0} {set angle [expr $angle+360]}
set coordox [lindex $line 0]
puts $outputfile "$coordox $angle"
puts "CdF : $coordox $angle"
}
}
set line [gets $inputfile]
set finfichier [eof $inputfile]
}
}



désolé pour la mise en page, mes tabulations n'ont pas étés conservées.

Erikr le Rouge
09/07/2008, 14h14
Ca y est j'ai trouvé : pour une fois que je ne suis pas "carré", ça m'apprendra.

Je n'ai pas fermé mes handle de fichier, et le comportement d'un handle doit être proche de celui d'une clef USB : écriture asynchrone, donc "il se peut que l'écriture ne soit définitive qu'au démontage" ce qui explique que ça ne marchait pas avec un petit fichier et que ça marchait un peu avec un gros.

J'ai amélioré au passage le code, si ça vous dit, il est en dessous :

A+

#!/usr/bin/tclsh

#Programme pour transformer un angle négatif en son homologue positif.
#Formule générale : nouvel angle = 360 - |ancien angle|

set path [pwd]
set infini 0

while {$infini==0} {
puts "Which file ? (ctrl-c to abort)"
set fi [gets stdin]
set fo [file rootname $fi]_mod360.dat
set hfi [open $path/$fi r]
set hfo [open $path/$fo a]
set i 0
while {[gets $hfi line] >= 0} {
set angle [lindex $line 1]
if {$angle<0} {set angle [expr $angle+360]}
puts "[lindex $line 0] $angle"
puts $hfo "[lindex $line 0] $angle"
}
close $hfi
close $hfo
}
unset path infini fi fo angle i hfo hfi

salv-ice
11/07/2008, 19h17
J'arrive un petit peu en retard mais si ça peut servir :

Dans beaucoup de langages, dont Tcl fait partie apparemment, les entrées / sorties utilisent un "buffer" qui est une sorte de tampon ou les données sont envoyées avant d'être envoyées dans le flux proprement dit. L'écriture ne se fait que lorsque le buffer est plein. Pour le vider, il est nécéssaire d'appeler une fonction "flush" afin de forcer le tampon à se vider. C'est probablement ce qui se passe lorsque tu referme tes handles de fichiers. Il ne s'agit donc pas d'écriture asynchrone mais bien d'un mécanisme de sécurité du langage de programmation.

Bonne soirée

Salv-ice.

Erikr le Rouge
16/07/2008, 15h22
J'arrive un petit peu en retard mais si ça peut servir :

Dans beaucoup de langages, dont Tcl fait partie apparemment, les entrées / sorties utilisent un "buffer" qui est une sorte de tampon ou les données sont envoyées avant d'être envoyées dans le flux proprement dit. L'écriture ne se fait que lorsque le buffer est plein. Pour le vider, il est nécéssaire d'appeler une fonction "flush" afin de forcer le tampon à se vider. C'est probablement ce qui se passe lorsque tu referme tes handles de fichiers. Il ne s'agit donc pas d'écriture asynchrone mais bien d'un mécanisme de sécurité du langage de programmation.

Bonne soirée

Salv-ice.[/b]


OK merci, pour l'info. Dans tous les cas, fermer le fichier ou faire un flush. Ceci dit, comme tu le sous entend, fermer le fichier doit être un alias du style "flusher + fermer" un peu comme le "eject /dev/hdc" doit démonter avant d'éjecter le CD de mon lecteur.

En fait, dans un petit fichier, il ne m'écrit rien car le tampon n'est pas plein. Dans un gros fichier, il écrit une partie car le tampon s'est rempli, une fois plein, il se vide dans mon ficher d'output, mais le reste du fichier d'input de suffit pas à le remplire une deuxième fois, donc si je ne ferme pas le fichier d'outuput, le tampon ne se vide pas dedans.

Dans le cas d'un autre fichier d'input plus gros, comme le nombre d'opération est différent (j'ai pas forcément autant d'angles dièdres négatifs) le tampon se vide à un autre moment et le tampon ne permet pas de remplire une ligne complète.

Un fois qu'on sait, c'est simple...

Merci encore et à+

phoenix
17/07/2008, 10h03
Ne pas oublier de mettre [Réglé] :)