SUPPRIMER LA LIGNE NUMERO N D'UN FICHIER TEXTE .TXT
cs_Alain Proviste
Messages postés908Date d'inscriptionjeudi 26 juillet 2001StatutModérateurDernière intervention 1 février 2015
-
21 août 2006 à 19:20
cs_jadot
Messages postés21Date d'inscriptionmardi 31 août 2004StatutMembreDernière intervention10 septembre 2007
-
28 août 2006 à 10:58
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.
cs_jadot
Messages postés21Date d'inscriptionmardi 31 août 2004StatutMembreDernière intervention10 septembre 2007 28 août 2006 à 10:58
Oui je ne dis pas le contraire, je ne parlais pas de ton code en particulier Mortalino.
C'etait juste une reflexion "generale" car parfois c'est tellement la "competition" du nombre de ligne que ca en devient illisible.
Je rejoins simplement l'idée d'Econs : "il pouvait même faire moins, mais çà aurait été moins lisible."
mortalino
Messages postés6786Date d'inscriptionvendredi 16 décembre 2005StatutMembreDernière intervention21 décembre 201118 28 août 2006 à 09:36
Salut Jadot,
dans ce cas précis, mon code est plus court et plus performant !
"si on supprime les commentaires ca fait moins de lignes mais ce n'est pas pour ca que c'est meilleur (que du contraire) ;-) "
Hors commentaires, j'ai qd même réduit son code de 50% !
++
cs_jadot
Messages postés21Date d'inscriptionmardi 31 août 2004StatutMembreDernière intervention10 septembre 2007 28 août 2006 à 08:49
Salut,
Pourquoi utiliser un fichier temporaire ?
On peut garder le tout en memoire dans un buffer et réécrire dans le fichier d'origine !
PS : A tout ceux qui comptent le nombre de lignes. Ce n'est pas le nombre de lignes qui fait la qualité d'un code, si on supprime les commentaires ca fait moins de lignes mais ce n'est pas pour ca que c'est meilleur (que du contraire) ;-)
MrJava_Javaman
Messages postés5Date d'inscriptionjeudi 2 février 2006StatutMembreDernière intervention 1 septembre 2007 22 août 2006 à 12:58
Oublier de dire que si tu change "gtLignCount" tu dois avec, changer "i" dans la fonction principal surtout si c'est au plus grand ...
MrJava_Javaman
Messages postés5Date d'inscriptionjeudi 2 février 2006StatutMembreDernière intervention 1 septembre 2007 22 août 2006 à 12:50
*** c'est la premiere commentaire pour maoi dans ce site :)
Alors j'utilise une fonction dans un "DLL" depuis longtemps je crois q'elle est tres utile .. elle a une maniere differente d'effacer une ligne mais elle peux etre redefiner d'une autre maniere ;
Ce que tu dois faire est d'ecrire ce ligne dans ton programme :
ensuite le "DLL" (ou le module comme tu veux) contient ces petites lignes :
01# Private Function gtLignCount(ByVal path as String) As Integer
02# Dim tmp As String
03# Open path For Input as #1
04# Do Until Eof(1)
05# Line Input #1, tmp
06# gtLignCount = gtLignCount + 1
07# Loop
08# Close #1
09# End Function
10# Function dlLigne(ByVal path As String, _
ByVal data As String, _
Optional SelStart As Byte = 1, _
Optional SelLen As Byte)
11# Dim txtArr() As String, i as Integer
12# ReDim txtArr(gtLignCount(path)) As String
13# Open path for Output As #1
14# For i = 0 To UBound(txtArr)
15# If Mid(txtArr(i), SelStart, SelLen) data Then i i + 1
16# Print #1, txtArr(i)
17# Next i
18# Close #1
19# End Function
20# 'By MrJava (Amahdy).
Remarques:
-"SelStart" et "SelLen" sont utilise pour savoir ou ce trouve le "data" donne ..
par exemple si le ligne contien un date puis un nom et je veux efface ce ligne quand je ne sais pas le date ;
du maniere si le ligne est comme ca :
21/10/2005_02:10:07 username=MrJava password=123
et bien sure je ne sais pas le password ou le date exactement mais je veux suprimer le user MrJava alors la fonction soit utilise comme ca :
# a.dlLigne FILE_PATH, "MrJava", 30, 6
-"SelStart" et "SelLen" sont en type "Byte" car un ligne peux pas contenir plus que 255 caractere tandis que "gtLignCount" est du type "Integer" ou si c'est plus large tu peux utilise "Long" .
***Excuser moi si j'ai fautes d'orthographe , je suis egyptien et pas d'une pays francaise ..
BRICE LA BIDOUILLE
Messages postés7Date d'inscriptionvendredi 21 juillet 2006StatutMembreDernière intervention22 octobre 2007 22 août 2006 à 09:34
Et bien en effet, de la fioriture en pagaille, c'est fou comme on croit faire bien!
En tous les cas merci de vos conseils, désolé d'avoir posté ce code qui a beaucoup de cousins!
Il est vrai que la programmation repond à des règles et des optimisations qui sont encore flous pour moi!
J'avoue que le code présenté ici est du bricolage mais malhereusement pour l'instant c'est la règle de tous mes développements.
Juste pour Icons la boucle:
For compteur = 1 To NbOC
TEMP = Mid(TEMP, InStr(1, TEMP, "") + 1)
Next
La variable maintes fois écrasé TEMP renvoie la chaîne de texte après le dernier "" donc le nom de fichier.
en rajoutant après next >
#POSITION_DERNIER_CARACTERE = len(Chemin_complet)- len(TEMP)
On obtient la position du dernier "" à la façon d'un "instr_der" si je peux me permettre.
Merci encore et je réflécherais à 2 fois avant de poster.
econs
Messages postés4030Date d'inscriptionmardi 13 mai 2003StatutMembreDernière intervention23 décembre 200824 22 août 2006 à 07:31
Et oui, 18 lignes, pas de fioritures ... il pouvait même faire moins, mais çà aurait été moins lisible.
mortalino
Messages postés6786Date d'inscriptionvendredi 16 décembre 2005StatutMembreDernière intervention21 décembre 201118 22 août 2006 à 02:05
Re, je t'ai fait un exemple (40 lignes, possibilité d'offrir le choix du fichier à l'utilisateur
et il choisi la ligne à supprimer dans un ListBox :
Ce qu'il faut :
* une Form
* un listbox nommé List1
* un Commandbutton nommé cbtValider
* le composant 'Microsoft Common Dialog 6.0' (dans 'ajouter composants...', tu le nommes dlgNomFichier
' *** dans les déclarations :
Dim sFichier As String, ff As Integer
Private Sub cbtValider_Click()
Dim i As Integer
If List1.ListIndex = -1 Then Exit Sub
List1.RemoveItem (List1.ListIndex)
Open sFichier For Output As #ff
For i = 1 To List1.ListCount
Print #ff, List1.List(i)
Next i
Close #ff
Annuler:
End Sub
Private Sub Form_Load()
Dim sLigne As String
With Me.dlgNomFichier
.CancelError = True
.Filter = "Base de données Access (*.txt)|*.txt"
.FilterIndex = 1
.InitDir = App.Path
On Error GoTo Annuler
.ShowOpen
End With
sFichier = Me.dlgNomFichier.FileName
ff = FreeFile
Open sFichier For Input As #ff
While Not EOF(ff)
Line Input #ff, sLigne
Me.List1.AddItem sLigne
Wend
Close #ff
Annuler:
End Sub
++
mortalino
Messages postés6786Date d'inscriptionvendredi 16 décembre 2005StatutMembreDernière intervention21 décembre 201118 21 août 2006 à 23:14
Arf, salut Manu, ;)
j'avais pas vu ton lien, c'est bien ce qui me semblait, avec une collection, c'est plus
court. Willy s'est gavé, 20 ou 30 lignes, j'étais loin du compte...
++
mortalino
Messages postés6786Date d'inscriptionvendredi 16 décembre 2005StatutMembreDernière intervention21 décembre 201118 21 août 2006 à 23:10
Salut,
1/ avec une collection, en 20 ou 30 lignes c'est faisable !!
2/ Ton code n'est pas dynamique, cela oblige l'utilisateur à connaitre la ligne à supprimer.
Il faut créer une Form, avec un contrôle reprenant chaque ligne du fichier texte,
l'utilisateur clique sur la ligne à supprimer.
++
econs
Messages postés4030Date d'inscriptionmardi 13 mai 2003StatutMembreDernière intervention23 décembre 200824 21 août 2006 à 21:30
Bon, alors il reste deux ou trois choses non mentionnées ci-dessus :
Au moins deux soucis dans la ligne qui suit : Le ° dans le nom de variable et le type Variant (beurk)
Dim N°ligne As Variant
Surtout, quel intérêt de la déclarer Variant si c'est pour la caster juste derrière en Int ?
N°ligne = CInt(N°ligne)
C'est quoi l'intérêt de cette boucle ? Tu affectes, et écrases à chaque tour la variable TEMP ... Le For et le Next peuvent être supprimés, puisque compteur n'est pas utilisé.
# For compteur = 1 To NbOC
# TEMP = Mid(TEMP, InStr(1, TEMP, "") + 1)
# Next
Ouvrir un fichier temporaire pour le fermer juste derrière ne présente aucun intérêt, puisque tu écris dans ce même fichier quelques lignes en dessous.
La condition
(Not (EOF(1) Or False))
peut se résumer ainsi : (Not (EOF(1)) ... Le False ne sert à rien. (x Or False = x)
C'est rigolo les Then vides ...
If compteur = N°ligne Then Else Print #2, text
Pourquoi ne pas jouer avec la négation de la condition dans ce cas ?
If compteur <> N°ligne Then Print #2, text
cs_Alain Proviste
Messages postés908Date d'inscriptionjeudi 26 juillet 2001StatutModérateurDernière intervention 1 février 20152 21 août 2006 à 20:14
ouch effectivement je n'avais pas vu les appels à fso ...
jean_marc_n2
Messages postés170Date d'inscriptionjeudi 11 décembre 2003StatutMembreDernière intervention24 janvier 2009 21 août 2006 à 20:01
Hello,
quelques conseils pour l'avenir:
- Il est d'usage d'indenter son code, c'est à dire de faire apparaître la structure logique de celui-ci par une utilisation judicieuse des tabulations. Exemple:
For i = 1 to 10
If condition Then
' je suis la
End If
Next i
- Il est incorrect d'ouvrir un fichier avec explicitement #1, #2, etc. On utilise à la place la fonction Freefile() qui renvoie le prochain numéro libre:
Dim f as Integer
f = Freefile
Open "truc.txt" for input as #f
Line Input #f, szBuffer
Close #f
- C'est bien d'avoir mis un mini traitement d'erreur dans compte_ligne, mais ça aurait été encore mieux de généraliser à toutes les fonctions
- Quitte à mettre un traitement d'erreur, autant le faire bien et renvoyer des infos utiles pour l'appelant, telles que: Numéro de l'erreur, Description de l'erreur. Libre ensuite à l'appelant d'en faire ce qu'il veut.
- L'utilisation de:
Set FSys = CreateObject("Scripting.FileSystemObject")
Set MonFic = FSys.CreateTextFile(CHEMIN_COMPLET_NOUVEAU_TXT)
est inutile (lent, une référence inutile, peu portable, j'en passe)! Il suffit de faire:
Dim f as Integer
f = Freefile
Open CHEMIN_COMPLET_NOUVEAU_TXT For Output As #f
Close #f
- La Sub suppr_ligne_TXT() serait à mon avis bien mieux en fonction, retournant des infos sur le bon (ou mauvais) déroulement des opérations.
Cordialement,
Jean-marc
cs_Alain Proviste
Messages postés908Date d'inscriptionjeudi 26 juillet 2001StatutModérateurDernière intervention 1 février 20152 21 août 2006 à 19:20
n'essaie pas de me faire croire que ça n'était pas déjà sur le site :|
sinon utilisez les fonctions de windows pour créer un fichier temporaire plutot que de le placer sur c: serait bienvenue.
28 août 2006 à 10:58
C'etait juste une reflexion "generale" car parfois c'est tellement la "competition" du nombre de ligne que ca en devient illisible.
Je rejoins simplement l'idée d'Econs : "il pouvait même faire moins, mais çà aurait été moins lisible."
28 août 2006 à 09:36
dans ce cas précis, mon code est plus court et plus performant !
"si on supprime les commentaires ca fait moins de lignes mais ce n'est pas pour ca que c'est meilleur (que du contraire) ;-) "
Hors commentaires, j'ai qd même réduit son code de 50% !
++
28 août 2006 à 08:49
Pourquoi utiliser un fichier temporaire ?
On peut garder le tout en memoire dans un buffer et réécrire dans le fichier d'origine !
PS : A tout ceux qui comptent le nombre de lignes. Ce n'est pas le nombre de lignes qui fait la qualité d'un code, si on supprime les commentaires ca fait moins de lignes mais ce n'est pas pour ca que c'est meilleur (que du contraire) ;-)
22 août 2006 à 12:58
22 août 2006 à 12:50
Alors j'utilise une fonction dans un "DLL" depuis longtemps je crois q'elle est tres utile .. elle a une maniere differente d'effacer une ligne mais elle peux etre redefiner d'une autre maniere ;
Ce que tu dois faire est d'ecrire ce ligne dans ton programme :
# a.dlLigne FILE_PATH, data_I_want_to_del,, len(data_I_want_to_del)
ensuite le "DLL" (ou le module comme tu veux) contient ces petites lignes :
01# Private Function gtLignCount(ByVal path as String) As Integer
02# Dim tmp As String
03# Open path For Input as #1
04# Do Until Eof(1)
05# Line Input #1, tmp
06# gtLignCount = gtLignCount + 1
07# Loop
08# Close #1
09# End Function
10# Function dlLigne(ByVal path As String, _
ByVal data As String, _
Optional SelStart As Byte = 1, _
Optional SelLen As Byte)
11# Dim txtArr() As String, i as Integer
12# ReDim txtArr(gtLignCount(path)) As String
13# Open path for Output As #1
14# For i = 0 To UBound(txtArr)
15# If Mid(txtArr(i), SelStart, SelLen) data Then i i + 1
16# Print #1, txtArr(i)
17# Next i
18# Close #1
19# End Function
20# 'By MrJava (Amahdy).
Remarques:
-"SelStart" et "SelLen" sont utilise pour savoir ou ce trouve le "data" donne ..
par exemple si le ligne contien un date puis un nom et je veux efface ce ligne quand je ne sais pas le date ;
du maniere si le ligne est comme ca :
21/10/2005_02:10:07 username=MrJava password=123
et bien sure je ne sais pas le password ou le date exactement mais je veux suprimer le user MrJava alors la fonction soit utilise comme ca :
# a.dlLigne FILE_PATH, "MrJava", 30, 6
-"SelStart" et "SelLen" sont en type "Byte" car un ligne peux pas contenir plus que 255 caractere tandis que "gtLignCount" est du type "Integer" ou si c'est plus large tu peux utilise "Long" .
***Excuser moi si j'ai fautes d'orthographe , je suis egyptien et pas d'une pays francaise ..
22 août 2006 à 09:34
En tous les cas merci de vos conseils, désolé d'avoir posté ce code qui a beaucoup de cousins!
Il est vrai que la programmation repond à des règles et des optimisations qui sont encore flous pour moi!
J'avoue que le code présenté ici est du bricolage mais malhereusement pour l'instant c'est la règle de tous mes développements.
Juste pour Icons la boucle:
For compteur = 1 To NbOC
TEMP = Mid(TEMP, InStr(1, TEMP, "") + 1)
Next
La variable maintes fois écrasé TEMP renvoie la chaîne de texte après le dernier "" donc le nom de fichier.
en rajoutant après next >
#POSITION_DERNIER_CARACTERE = len(Chemin_complet)- len(TEMP)
On obtient la position du dernier "" à la façon d'un "instr_der" si je peux me permettre.
Merci encore et je réflécherais à 2 fois avant de poster.
22 août 2006 à 07:31
22 août 2006 à 02:05
et il choisi la ligne à supprimer dans un ListBox :
Ce qu'il faut :
* une Form
* un listbox nommé List1
* un Commandbutton nommé cbtValider
* le composant 'Microsoft Common Dialog 6.0' (dans 'ajouter composants...', tu le nommes dlgNomFichier
' *** dans les déclarations :
Dim sFichier As String, ff As Integer
Private Sub cbtValider_Click()
Dim i As Integer
If List1.ListIndex = -1 Then Exit Sub
List1.RemoveItem (List1.ListIndex)
Open sFichier For Output As #ff
For i = 1 To List1.ListCount
Print #ff, List1.List(i)
Next i
Close #ff
Annuler:
End Sub
Private Sub Form_Load()
Dim sLigne As String
With Me.dlgNomFichier
.CancelError = True
.Filter = "Base de données Access (*.txt)|*.txt"
.FilterIndex = 1
.InitDir = App.Path
On Error GoTo Annuler
.ShowOpen
End With
sFichier = Me.dlgNomFichier.FileName
ff = FreeFile
Open sFichier For Input As #ff
While Not EOF(ff)
Line Input #ff, sLigne
Me.List1.AddItem sLigne
Wend
Close #ff
Annuler:
End Sub
++
21 août 2006 à 23:14
j'avais pas vu ton lien, c'est bien ce qui me semblait, avec une collection, c'est plus
court. Willy s'est gavé, 20 ou 30 lignes, j'étais loin du compte...
++
21 août 2006 à 23:10
1/ avec une collection, en 20 ou 30 lignes c'est faisable !!
2/ Ton code n'est pas dynamique, cela oblige l'utilisateur à connaitre la ligne à supprimer.
Il faut créer une Form, avec un contrôle reprenant chaque ligne du fichier texte,
l'utilisateur clique sur la ligne à supprimer.
++
21 août 2006 à 21:30
Au moins deux soucis dans la ligne qui suit : Le ° dans le nom de variable et le type Variant (beurk)
Dim N°ligne As Variant
Surtout, quel intérêt de la déclarer Variant si c'est pour la caster juste derrière en Int ?
N°ligne = CInt(N°ligne)
C'est quoi l'intérêt de cette boucle ? Tu affectes, et écrases à chaque tour la variable TEMP ... Le For et le Next peuvent être supprimés, puisque compteur n'est pas utilisé.
# For compteur = 1 To NbOC
# TEMP = Mid(TEMP, InStr(1, TEMP, "") + 1)
# Next
Ouvrir un fichier temporaire pour le fermer juste derrière ne présente aucun intérêt, puisque tu écris dans ce même fichier quelques lignes en dessous.
La condition
(Not (EOF(1) Or False))
peut se résumer ainsi : (Not (EOF(1)) ... Le False ne sert à rien. (x Or False = x)
C'est rigolo les Then vides ...
If compteur = N°ligne Then Else Print #2, text
Pourquoi ne pas jouer avec la négation de la condition dans ce cas ?
If compteur <> N°ligne Then Print #2, text
Je crois qu'on peut arrêter là d'accabler ce code. Il est très perfectible.
Et déjà présent dans les snippets de codyx.org, en beaucoup moins de lignes :
http://www.codyx.org/snippet_supprimer-ou-plusieurs-lignes-dans-fichier_76.aspx
21 août 2006 à 20:14
21 août 2006 à 20:01
quelques conseils pour l'avenir:
- Il est d'usage d'indenter son code, c'est à dire de faire apparaître la structure logique de celui-ci par une utilisation judicieuse des tabulations. Exemple:
For i = 1 to 10
If condition Then
' je suis la
End If
Next i
- Il est incorrect d'ouvrir un fichier avec explicitement #1, #2, etc. On utilise à la place la fonction Freefile() qui renvoie le prochain numéro libre:
Dim f as Integer
f = Freefile
Open "truc.txt" for input as #f
Line Input #f, szBuffer
Close #f
- C'est bien d'avoir mis un mini traitement d'erreur dans compte_ligne, mais ça aurait été encore mieux de généraliser à toutes les fonctions
- Quitte à mettre un traitement d'erreur, autant le faire bien et renvoyer des infos utiles pour l'appelant, telles que: Numéro de l'erreur, Description de l'erreur. Libre ensuite à l'appelant d'en faire ce qu'il veut.
- L'utilisation de:
Set FSys = CreateObject("Scripting.FileSystemObject")
Set MonFic = FSys.CreateTextFile(CHEMIN_COMPLET_NOUVEAU_TXT)
est inutile (lent, une référence inutile, peu portable, j'en passe)! Il suffit de faire:
Dim f as Integer
f = Freefile
Open CHEMIN_COMPLET_NOUVEAU_TXT For Output As #f
Close #f
- La Sub suppr_ligne_TXT() serait à mon avis bien mieux en fonction, retournant des infos sur le bon (ou mauvais) déroulement des opérations.
Cordialement,
Jean-marc
21 août 2006 à 19:20
sinon utilisez les fonctions de windows pour créer un fichier temporaire plutot que de le placer sur c: serait bienvenue.