Supprimer ligne dans fichier texte

Résolu
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 - 13 oct. 2010 à 18:26
NHenry Messages postés 15156 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 29 septembre 2024 - 16 oct. 2010 à 13:10
Bonjour, voila j'ai un code qui doit supprimer la ligne de texte comportant le mot prédéfini. Le problème est que le code génère l'erreur :
L'index était hors limites. Il ne doit pas être négatif et doit être inférieur à la taille de la collection. Nom du paramètre : index

A mon avis le RemoveAt(i) pose problème car il supprime une ligne et cela décale le n° des lignes et au final ca les suppriment toutes.
For Each files In My.Computer.FileSystem.GetFiles(TextBox1.Text, FileIO.SearchOption.SearchAllSubDirectories, "*txt")
                Dim lines As List(Of String) = System.IO.File.ReadAllLines(files).ToList
                If lines.Count = 0 Then Continue For ' ne passe pas à la ligne de dessous mais remonte pour traiter le prochain fichier
                For i As Integer = 0 To lines.Count - 1
                    If lines(i).Contains("toto") Then
                        lines.RemoveAt(i)
                    End If
                Next
            Next

Qu'en pensez-vous ?

Ma LV2 c'est le Visual Basic, et toi ?

23 réponses

NHenry Messages postés 15156 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 29 septembre 2024 159
13 oct. 2010 à 21:20
Bonjour,

For Each files In My.Computer.FileSystem.GetFiles(TextBox1.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.txt")
'' J'ai remis le point entre * et txt
            Dim lines As List(Of String) = System.IO.File.ReadAllLines(files).ToList
            If lines.Count = 0 Then Continue For
            For i = lines.Count - 1 To 0 Step -1
                If lines(i).Contains("toto") Then
                    lines.RemoveAt(i)
                End If
            Next
            System.IO.File.WriteAllLines(files, lines.ToArray)
        Next


Ajoute le .ToArray à la ligne d'écriture.

1
raffika Messages postés 269 Date d'inscription dimanche 31 mai 2009 Statut Membre Dernière intervention 12 mars 2011
13 oct. 2010 à 19:15
Salut,
tu as oublié de rajouter 1 à i lorsque
tu supprime une ligne avec RemoveAt.
If lines(i).Contains("toto") Then
lines.RemoveAt(i):i+=1
End If
0
NHenry Messages postés 15156 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 29 septembre 2024 159
13 oct. 2010 à 19:16
Bonjour,

                For i As Integer = 0 To lines.Count - 1
                    If lines(i).Contains("toto") Then
                        lines.RemoveAt(i)
                    End If
                Next


Si ta ligne contient "toto", tu la retire, donc ça fait une ligne de moins.
Mais les bornes du For ne sont calculées qu'au début de la boucle, donc, une modification du nombre de lignes en cours de boucle, ne sera pas prise en compte.

2 solutions :
Soit un If pour faire un Exit For si i>Lines.count-1
soit plus fin, partir de la dernière ligne pour remonter :
For i As Integer = 0 To lines.Count - 1
deviendrait :
For i As Integer = lines.Count - 1 to 0 step -1

0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
13 oct. 2010 à 19:28
J'ai essayé la soluce de raffika, mais c'est toujours la même erreur
NHenry, j'ai essayé ta soluce n°2 qui donne la même erreur mais je comprend pas la n°1 :
Soit un If pour faire un Exit For si i>Lines.count-1

Vraiment bizard


Ma LV2 c'est le Visual Basic, et toi ?
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
raffika Messages postés 269 Date d'inscription dimanche 31 mai 2009 Statut Membre Dernière intervention 12 mars 2011
13 oct. 2010 à 19:48
Ah oui ma solution ne marche pas,
mais comment ça se fait que si i est plus
grand que lines.count-1 la boucle for n'est pas stoppée ?
@aus3004 pour la première solution de NHenry, ça donnes :
For i As Integer = 0 To lines.Count - 1

If i > lines.Count - 1 Then
Exit For
End If
If lines(i).Contains("toto") Then
lines.RemoveAt(i) : i += 1
End If

Next
Pour la seconde, ça donne :
If lines(i).Contains("toto") Then
lines.RemoveAt(i) : i += 1
End If
Salutations
0
raffika Messages postés 269 Date d'inscription dimanche 31 mai 2009 Statut Membre Dernière intervention 12 mars 2011
13 oct. 2010 à 19:50
PS : Euh, enleves les i+=1 ;)
0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
13 oct. 2010 à 20:13
Merci raffika, j'ai essayé la soluce n°1 de NHenri mais rien ne ce passe !
Les deux documents texte ayant chacun une ligne comportant le mot prédéfini n'ont pas changés.



Ma LV2 c'est le Visual Basic, et toi ?
0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
13 oct. 2010 à 20:15
Merci raffika, j'ai essayé la soluce n°1 de NHenri mais rien ne ce passe !

Je te remercie de m'avoir expliqué le code même si ca marche pas ca veut dire. lol.


Ma LV2 c'est le Visual Basic, et toi ?
0
raffika Messages postés 269 Date d'inscription dimanche 31 mai 2009 Statut Membre Dernière intervention 12 mars 2011
13 oct. 2010 à 20:33
J'ai essayé les deux solutions de NHenry,
avec un fichier texte avec plusieurs lignes,
certaines contenant toto, ensuite
dans une boucle for je regarde le résultat :
for i=0 to lines.count-1
msgbox(lines(i))
next i '' donc après la modification bien sur
Qu'est ce que tu veux dire par ne marche pas ?
Quel résultat tu veux obtenir ?
0
raffika Messages postés 269 Date d'inscription dimanche 31 mai 2009 Statut Membre Dernière intervention 12 mars 2011
13 oct. 2010 à 20:45
Essayes :
        For Each files In My.Computer.FileSystem.GetFiles(TextBox1.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.txt")
'' J'ai remis le point entre * et txt
            Dim lines As List(Of String) = System.IO.File.ReadAllLines(files).ToList
            If lines.Count = 0 Then Continue For
            For i = lines.Count - 1 To 0 Step -1
                If lines(i).Contains("toto") Then
                    lines.RemoveAt(i)
                End If
            Next
            System.IO.File.WriteAllLines(TextBox1.Text, lines) '?
        Next

Salutations
0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
13 oct. 2010 à 20:45
Ah, dsl j'ai peut être pas été assez claire.
Il faut que tous les fichiers texte de la boucle soient modifiés avec :
toutes les lignes comportant le mot prédéfini soient supprimées.


Ma LV2 c'est le Visual Basic, et toi ?
0
raffika Messages postés 269 Date d'inscription dimanche 31 mai 2009 Statut Membre Dernière intervention 12 mars 2011
13 oct. 2010 à 20:58
Alors c'est :
        For Each files In My.Computer.FileSystem.GetFiles(TextBox1.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.txt")

            Dim lines As List(Of String) = System.IO.File.ReadAllLines(files).ToList
            If lines.Count = 0 Then Continue For

            If lines.Count = 0 Then Continue For
            For i = lines.Count - 1 To 0 Step -1
                If lines(i).Contains("toto") Then
                    lines.RemoveAt(i)
                End If
            Next
            System.IO.File.WriteAllLines(files, lines)
        Next
0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
13 oct. 2010 à 21:00
Oups, une petite erreur sur le dernier lines :

Une valeur de type 'System.Collections.Generic.List(Of String)' ne peut pas être convertie en 'Tableau à 1 dimension(s) de String'.



Ma LV2 c'est le Visual Basic, et toi ?
0
NHenry Messages postés 15156 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 29 septembre 2024 159
13 oct. 2010 à 21:02
Bonjour,

Je reprend le code de Raffika (qui a utilisé la 2ième solution que j'évoquais) :
        For Each files In My.Computer.FileSystem.GetFiles(TextBox1.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.txt")
'' J'ai remis le point entre * et txt
            Dim lines As List(Of String) = System.IO.File.ReadAllLines(files).ToList
            If lines.Count = 0 Then Continue For
            For i = lines.Count - 1 To 0 Step -1
                If lines(i).Contains("toto") Then
                    lines.RemoveAt(i)
                End If
            Next
            System.IO.File.WriteAllLines(files, lines)
        Next


Normalement, ça devrait fonctionner.

0
Sehnsucht Messages postés 107 Date d'inscription samedi 25 novembre 2000 Statut Membre Dernière intervention 4 mai 2013
13 oct. 2010 à 21:02
Bonsoir,

Tu peux tenter ceci j'ai commenté pour expliquer, mais s'il te reste des questions n'hésite pas

Dim files(), lines() As String
Dim output As New List(Of String)

Try

    ' Récupère les chemins des fichiers
    files = IO.Directory.GetFiles(TextBox1.Text, "*txt", IO.SearchOption.AllDirectories)

    For Each file In files
        ' Vide la liste
        output.Clear()

        ' Récupère les lignes du fichier
        lines = IO.File.ReadAllLines(file)

        For Each line In lines
            ' Si la ligne ne contient pas 'toto' on l'ajoute à la liste
            If Not line.Contains("toto") Then
                output.Add(line)
            End If
        Next

        ' Ne réécrit le fichier que si le contenu à changé
        ' autrement dit si son nombre de ligne a baissé
        If output.Count < lines.Length Then
            ' Je réécris dans le même fichier, si tu ne le souhaites pas
            ' pense à changer le 1er paramètre
            System.IO.File.WriteAllLines(file, output)
        End If
    Next

Catch ex As Exception
    ' En cas de problème (si un fichier est utilisé par une autre application par exemple)
    MessageBox.Show(ex.Message, "Une erreur est survenue")
End Try


Cordialement !
0
NHenry Messages postés 15156 Date d'inscription vendredi 14 mars 2003 Statut Modérateur Dernière intervention 29 septembre 2024 159
13 oct. 2010 à 21:02
Un peu de retard, pas grave :)
0
raffika Messages postés 269 Date d'inscription dimanche 31 mai 2009 Statut Membre Dernière intervention 12 mars 2011
13 oct. 2010 à 21:11
@aus3004 oui effectivement, pourtant le code
que je t'ai donné marche sur VB 2010...
Mais pas sur VB 2008
Je te tiens au courant...
Bonsoir
0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
13 oct. 2010 à 21:14
Ouais merci les gars ca avance grave

Mais dans chacun de vos codes il y a 1 erreur.

For Each files In My.Computer.FileSystem.GetFiles(TextBox1.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.txt")
'' J'ai remis le point entre * et txt
            Dim lines As List(Of String) = System.IO.File.ReadAllLines(files).ToList
            If lines.Count = 0 Then Continue For
            For i = lines.Count - 1 To 0 Step -1
                If lines(i).Contains("toto") Then
                    lines.RemoveAt(i)
                End If
            Next
            System.IO.File.WriteAllLines(files, lines)
        Next

Une valeur de type 'System.Collections.Generic.List(Of String)' ne peut pas être convertie en 'Tableau à 1 dimension(s) de String'.

Dim files(), lines() As String
            Dim output As New List(Of String)


            ' Récupère les chemins des fichiers
            files = IO.Directory.GetFiles(TextBox1.Text, "*txt", IO.SearchOption.AllDirectories)

            For Each file In files
                ' Vide la liste
                output.Clear()

                ' Récupère les lignes du fichier
                lines = IO.File.ReadAllLines(file)

                For Each line In lines
                    ' Si la ligne ne contient pas 'toto' on l'ajoute à la liste
                    If Not line.Contains("toto") Then
                        output.Add(line)
                    End If
                Next

                ' Ne réécrit le fichier que si le contenu à changé
                ' autrement dit si son nombre de ligne a baissé
                If output.Count < lines.Length Then
                    ' Je réécris dans le même fichier, si tu ne le souhaites pas
                    ' pense à changer le 1er paramètre
                    System.IO.File.WriteAllLines(file, output)
                End If
            Next

Une valeur de type 'System.Collections.Generic.List(Of String)' ne peut pas être convertie en 'Tableau à 1 dimension(s) de String'.




Ma LV2 c'est le Visual Basic, et toi ?
0
raffika Messages postés 269 Date d'inscription dimanche 31 mai 2009 Statut Membre Dernière intervention 12 mars 2011
13 oct. 2010 à 21:31
Il reste bien entendu cette dernière solution,
qui marches, selon le principe que la dernière ligne
contiendra obligatoirement un Environment.Newline
mais qui peut être modifié ...
        For Each files In My.Computer.FileSystem.GetFiles(TextBox1.Text, FileIO.SearchOption.SearchAllSubDirectories, "*.txt")

            Dim lines As List(Of String) = System.IO.File.ReadAllLines(files).ToList
            If lines.Count = 0 Then Continue For

            If lines.Count = 0 Then Continue For
            For i = lines.Count - 1 To 0 Step -1
                If lines(i).Contains("toto") Then
                    lines.RemoveAt(i)
                End If
            Next

            Dim resultat As String = "" '' On crée une variable string

            For i = 0 To lines.Count - 1
                resultat &= lines(i) & Environment.NewLine 
'' on met les lignes de 'lines' une par unes suivies de 
'' Environment.Newline (retour à la ligne)
            Next

'' et on écrit le fichier selon la méthode Writealltext
'' qui écrit la string resultat dans le fichier files
            System.IO.File.WriteAllText(files, resultat)


        Next

Salutations
0
cs_aus3004 Messages postés 319 Date d'inscription jeudi 1 avril 2010 Statut Membre Dernière intervention 16 mars 2011 1
13 oct. 2010 à 23:03
J'ai pris le dernier code de NHenry, c'est impec !
@NHenry, mdr ta signature, moi je connais la Haute Autorité pour le Développement Optimal du Piratage sur Internet

Une dernière question, est-ce que cela marche avec tous les fichiers de texte à votre avis (dsl, je peux pas tester) ?

Ma LV2 c'est le Visual Basic, et toi ?
0
Rejoignez-nous