Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Rajouter une ligne en début de fichier

10 views
Skip to first unread message

clipper

unread,
Oct 19, 2009, 11:55:46 AM10/19/09
to
Salut � tous

Comme le titre l'indique, je voudrais rajouter une ligne en d�but d'un
fichier texte. J'ai beau parcourir dans tous les sens le manuel sur
"open" "puts" et "file", je n'arrive pas � trouver un moyen d'y arriver.

Quelqu'un aurait une id�e ?

--
Clipper, qui, d'habitude, trouve la solution presque imm�diatement apr�s
avoir post�.

Kroc

unread,
Oct 19, 2009, 12:01:18 PM10/19/09
to
set fin [open $fichier r]
set data [read $fin]
close $fin
set fout [open $fichier w]
puts $fout $maligne
puts -nonewline $fout $data
close $fout

--
David Zolli

clipper

unread,
Oct 19, 2009, 12:10:02 PM10/19/09
to
Kroc a �crit :

D'accord. Si je comprends bien tout, en fait on ne peut pas se d�placer
dans un fichier et rajouter des lignes, donc on cr�e un nouveau fichier
avec la ligne, puis on y ajoute le contenu de l'ancien fichier.
j'y avais pens� mais je me disais qu'il pouvait y avoir une subtilit�
quelque part que je n'avais pas vue et qui permettait de faire mieux.

merci pour cette r�ponse.

--
Clipper

Gerard Sookahet

unread,
Oct 20, 2009, 1:44:27 PM10/20/09
to
Bonsoir,

Quelque soit le langage, pour écrire dans un fichier,
on est obligé de le monter en mémoire. Autrement dit
de le mettre dans une variable.

Le mécanisme qui consiste à concaténer la ligne à ajouter
et le reste du fichier est nettement visible avec Tcl,
mais il en est de même dans d'autres langages.
Sauf que parfois ce mécanisme est masqué par la syntaxe du langage.

Pour insérer une ligne dans un fichier texte à la nième
ligne, la meilleure stratégie reste de mettre le contenu
fichier dans une variable, de faire un "split" sur les
retours chariot ("\n") et d'insérer la ligne avec linsert.

Si l'on veut naviguer plus finement, il existe la commande "seek".
Mais elle est utilisé au niveau des octets et pas des caractères.

GS

Kroc

unread,
Oct 22, 2009, 4:38:42 AM10/22/09
to
C'est pourtant vrai qu'un :

set fin [open $fichier p] ; # avec p = prepend comme a = append

ça ne serait pas une mauvaise idée.

--
David Zolli

clipper

unread,
Oct 22, 2009, 10:56:15 AM10/22/09
to
Kroc a �crit :

> C'est pourtant vrai qu'un :
>
> set fin [open $fichier p] ; # avec p = prepend comme a = append
>
> �a ne serait pas une mauvaise id�e.
>
> --
> David Zolli

oui, hein, �a pourrait �tre pratique !

--
Clipper

Gerard Sookahet

unread,
Oct 22, 2009, 1:25:08 PM10/22/09
to

Bonsoir,

Pour ajouter une ligne en début de fichier avec la commande "seek":

set f [open monfichier.txt a]
seek $f 0 start
puts $f "La première ligne"
close $f

Pour faire la même chose en fin de fichier:

seek $f 0 end


GS

Eric Hassold

unread,
Oct 22, 2009, 7:47:22 PM10/22/09
to
Bonsoir,

Gerard Sookahet a �crit :
> Bonsoir,
>
> Pour ajouter une ligne en d�but de fichier avec la commande "seek":


>
> set f [open monfichier.txt a]
> seek $f 0 start

> puts $f "La premi�re ligne"
> close $f
>

C'est incorrect. Si un fichier est ouvert avec le mode "a", toutes les
ecritures sont effectuees a la fin du fichier, peu importe quel etait la
position du curseur juste avant le [puts] (donc le seek ci-dessus n'a
aucun effet sur ce que fait le puts, et "La premiere ligne" est ecrite
en fin de fichier).

En ouvrant le fichier en mode "r+", le code ci-dessus permettrait
d'ecrire la ligne "La premiere ligne " en tete de fichier, mais en
ecrasant le contenu precedent du fichier, et non en l'inserant
(intercalant) avant le contenu.

Quant au mode "p" sorti de l'imagination de David, je rappelle juste
(comme l'a deja evoque Gerard) que sa non-existence ne resulte pas d'une
fonctionnalite manquante dans Tcl, mais juste dans le fait que quasiment
aucun systeme de fichiers (filesystem) n'est concu pour permettre cette
operation.

La lecture en memoire, puis reecriture du contenu, est la methode
triviale, la plus facile a mettre en oeuvre. Cependant, si le fichier
est large, cela peut couter cher, voire etre impossible (essayer donc de
charger un le contenu d'un .iso de 4.7G dans une chaine Tcl, surtout sur
un systeme 32bits :p). Autre probleme de cette approche, si
quelquechose se passe mal pendant la copie, le contenu du fichier est
perdu. L'autre solution intuitive est donc de passer par un fichier
temporaire, puis d'ecraser le fichier original une fois le fichier
temporaire complet. Mais la, ca peut couter cher sur le disque dur.

Reste donc la solution de faire le decalage du fichier en place, par
exemple avec le code ci-dessous.

Eric

-----
Eric Hassold
Evolane - http://www.evolane.com/


-----

# Ecriture dans un fichier par insertion (en tete ou au milieu du
# fichier), sans lire le contenu du fichier en RAM, ni utiliser
# de copie temporaire, afin de permettre de travailler avec des
# fichiers larges
proc finsert {f buf {where 0}} {
# Open file
set fd [open $f r+]
fconfigure $fd -translation binary -encoding binary
if {$where>0} {
seek $fd $where start
}

# On se souvient de ou inserer le tampon $buf
set pstart [tell $fd]

# Ajuste la taille du fichier a la taille finale
seek $fd 0 end
set p0 [tell $fd]
puts -nonewline $fd $buf
set p1 [tell $fd]

# Decalage a appliquer
set shift [expr {$p1-$p0}]

# Memoire a utiliser pour la copie. Inutile de monter trop,
# ce qui n'apporterait aucun gain en performance, mais
# ne pas utiliser une valeur ridiculement petite, pour eviter
# les coups des [seek]
set bsize [expr {1024*1024}]

# Taille du bloc a deplacer (en octets)
set tomove [expr {$p0-$pstart}]

# Decalage
set done 0
while {$done<$tomove} {
set p [expr {$p0-$bsize}]
if {$p<$pstart} {
set p $pstart
}
set tmplen [expr {$p0-$p}]

seek $fd $p start
set tmp [read $fd $tmplen]
seek $fd [expr {$p+$shift}]
puts -nonewline $fd $tmp

set p0 $p
incr done $tmplen
}

# Ecriture du buffer a sa position cible
seek $fd $pstart
puts -nonewline $fd $buf

# That's all folks
close $fd

return
}

# Insertion en tete n'est qu'un cas particulier
proc prepend {f buf} {
return [finsert $f $buf 0]
}

# Pour inserer une ligne en tete du fichier toto.txt
# prepend toto.txt "Hello\n"

Kroc

unread,
Oct 23, 2009, 3:12:50 AM10/23/09
to
On 23 oct, 01:47, Eric Hassold <hass...@evolane.com> wrote:
> Quant au mode "p" sorti  de l'imagination de David, je rappelle juste
> (comme l'a deja evoque Gerard) que sa non-existence ne resulte pas d'une
> fonctionnalite manquante dans Tcl, mais juste dans le fait que quasiment
> aucun systeme de fichiers (filesystem) n'est concu pour permettre cette
> operation.
Je ne voyais pas ça comme un vrai prepend (directement sur le disque),
mais comme un mode qui simulerai un prepend en faisant comme ton
finsert mais en C dans le coeur de Tcl.

En plus, comme les données des fichiers n'ont plus besoin d'être
écrites consécutivement sur le disque depuis qu'on a des tables
d'allocation à peut près potables, un vrai prepend ne devrait pas être
insurmontable (mais c'est un autre sujet).

--
David Zolli

Vincent Verdon

unread,
Oct 23, 2009, 3:45:03 PM10/23/09
to
Bonsoir � tous,

Eric Hassold a �crit :

>
> La lecture en memoire, puis reecriture du contenu, est la methode
> triviale, la plus facile a mettre en oeuvre. Cependant, si le fichier
> est large, cela peut couter cher, voire etre impossible (essayer donc de
> charger un le contenu d'un .iso de 4.7G dans une chaine Tcl, surtout sur
> un systeme 32bits :p). Autre probleme de cette approche, si
> quelquechose se passe mal pendant la copie, le contenu du fichier est
> perdu. L'autre solution intuitive est donc de passer par un fichier
> temporaire, puis d'ecraser le fichier original une fois le fichier
> temporaire complet. Mais la, ca peut couter cher sur le disque dur.

Peut-�tre que la solution s�re consiste alors � utiliser la
concat�nation de fichiers en passant par une commande externe, genre :
echo ligne_a_ajouter > f1
cat f1 f2 > f3
On a ajout� ainsi la ligne dans f2 et enregistr� cela dans f3

Sous Win, je crois me souvenir qu'on peut concat�ner en faisant copy
f1+f2 f3

Evidemment, on doit ensuite effacer f2 et renommer f3 en f2.

Bon, on n'est plus dans une solution tcl, je sais ;-)

Amicalement, Vincent Verdon

Vincent Verdon

unread,
Oct 24, 2009, 5:08:29 AM10/24/09
to
Vincent Verdon a �crit :

> Bonsoir � tous,
>
> Eric Hassold a �crit :
>
>>
>> La lecture en memoire, puis reecriture du contenu, est la methode
>> triviale, la plus facile a mettre en oeuvre. Cependant, si le fichier
>> est large, cela peut couter cher, voire etre impossible (essayer donc
>> de charger un le contenu d'un .iso de 4.7G dans une chaine Tcl,
>> surtout sur un systeme 32bits :p). Autre probleme de cette approche,
>> si quelquechose se passe mal pendant la copie, le contenu du fichier
>> est perdu. L'autre solution intuitive est donc de passer par un
>> fichier temporaire, puis d'ecraser le fichier original une fois le
>> fichier temporaire complet. Mais la, ca peut couter cher sur le disque
>> dur.
>
> Peut-�tre que la solution s�re consiste alors � utiliser la
> concat�nation de fichiers en passant par une commande externe, genre :
> echo ligne_a_ajouter > f1
> cat f1 f2 > f3
> On a ajout� ainsi la ligne dans f2 et enregistr� cela dans f3
>
> Sous Win, je crois me souvenir qu'on peut concat�ner en faisant copy
> f1+f2 f3
Je viens de tester dans ma dosbox, c'est bien cela.

florentis

unread,
Oct 28, 2009, 8:11:39 PM10/28/09
to
On 23 oct, 20:45, Vincent Verdon <vincent.ver...@laposte.net> wrote:
> Bonsoir à tous,
>
> Eric Hassold a écrit :

>
>
>
> > La lecture en memoire, puis reecriture du contenu, est la methode
> > triviale, la plus facile a mettre en oeuvre. Cependant, si le fichier
> > est large, cela peut couter cher, voire etre impossible (essayer donc de
> > charger un le contenu d'un .iso de 4.7G dans une chaine Tcl, surtout sur
> >  un systeme 32bits :p). Autre probleme de cette approche, si
> > quelquechose se passe mal pendant la copie, le contenu du fichier est
> > perdu. L'autre solution intuitive est donc de passer par un fichier
> > temporaire, puis d'ecraser le fichier original une fois le fichier
> > temporaire complet. Mais la, ca peut couter cher sur le disque dur.
>
> Peut-être que la solution sûre consiste alors à utiliser la
> concaténation de fichiers en passant par une commande externe, genre :

> echo ligne_a_ajouter > f1
> cat f1 f2 > f3
> On a ajouté ainsi la ligne dans f2 et enregistré cela dans f3
>
> Sous Win, je crois me souvenir qu'on peut concaténer en faisant copy

> f1+f2 f3
>
> Evidemment, on doit ensuite effacer f2 et renommer f3 en f2.
>
> Bon, on n'est plus dans une solution tcl, je sais ;-)
>
> Amicalement, Vincent Verdon

sinon il y a aussi dans le package fileutil de la librairie tcl la
commande
::fileutil::insertIntoFile

Je suppose que l'algorithme doit ressembler à celui d'Eric. L'idée de
Kroc de reprendre cet algorithme en C est intéressante.

0 new messages