Partage
  • Partager sur Facebook
  • Partager sur Twitter

[VB.NET] Réutiliser les variables d'un .txt

Récupérer des variables qui ont été stockées dans un fichier .txt

    4 mars 2020 à 10:41:18

    Bonjour,

    Je rencontre un problème pour un projet où j'ai besoin d'extraire des données stockées dans un fichier texte, pour les réutiliser dans un programme en VB.NET en tant que variables et faire une série de calculs avec.

    Pour un projet j’utilise LS-OPT. C'est un logiciel d'optimisation utilisé pas mal en ingénierie. Le problème est qu'il doit impérativement être couplé avec un solveur type MATLAB, Excel ou encore un solveur fait maison (ce qui est mon cas).
    La procédure est la suivante : l'utilisateur fournit des valeurs numériques initiales plus ou moins arbitraire directement à LS-OPT, pour qu'il puisse les communiquer au solveur. Ensuite le solveur prend ces valeurs, fait des calculs et renvoie une réponse dans un fichier texte qui sera lu par LS-OPT. LS-OPT analyse la réponse, et détermine quelles nouvelles valeurs numériques il doit donner au solveur pour qu'a l'itération suivante le résultat donné par le solveur soit plus proche du résultat que souhaite obtenir l'utilisateur, et ainsi de suite jusqu'à ce que les résultats renvoyés pas le solveur soit compris dans une marge d'erreur préalablement définie par l'utilisateur.

    Ces 2 programmes communiqueront donc en boucle un certain nombre de fois, puis s’arrêteront.

    Pour vous détailler un peu plus, le logiciel LS-OPT me renvoie en sortie un fichier texte structuré avec des valeurs comme ci-dessous :
    5.00000e+001 1.50000e+002 2.99999e-001
    Coef1 Coef2 Coef3

    Ce fichier texte est donc ensuite utilisé en entrée de mon programme en VB.NET où je dois réutiliser les valeurs numériques stockées dans ce fichier. Je dois extraire la valeur du Coef1 (donc 5.00000e+001) et la stocker dans une variable "X" par exemple, puis extraire la valeur du Coef2 (donc 1.50000e+002) et la stocker dans une variable "Y" et idem avec la variable 3.

    À cela s'ajoute une difficulté, c'est que dans mon exemple je n'ai que 3 variables, mais en vérité ce nombre peut changer en fonction des besoins. Il me faut donc une solution qui peut s’adapter automatiquement au nombre de variables.

    Pour l'instant j'ai réussi à coder un bout de programme qui répond à toutes ces exigences en stockant les valeurs des variables et leur nom respectif dans un tableau à 2 lignes et n colonnes (ou l’inverse je ne sais pas). Le seul problème qui me reste est que le tableau est détruit à la sortie de ma boucle… :’(

    Je pense donc ne pas être très loin de la solution et qu'il ne reste plus qu'à trouver un moyen de conserver le tableau et ses valeurs afin de pouvoir les réutiliser dans tout mon programme VB.NET.

    J’ai cherché un peu partout, mais comme je suis novice en VB.NET, je suis peut-être passé à côté de la solution sur le forum sans comprendre qu’elle était sous mes yeux… J’en appelle donc à votre aide.

    Merci

    Je vous mets le code que j’ai fait ci-dessous.


    PS : j’utilise Visual Studio 2010 Express au cas où ça aurait son importance…



    Module Module1
    
        Sub Main()
            Dim i As Integer = 0    'déclaration et initialisation des compteurs.
            Dim j As Integer = 0    'déclaration et initialisation des compteurs.
    
            Using MyReader As New Microsoft.VisualBasic.
                          FileIO.TextFieldParser("C:\blablabla\ConsoleApplication1\MonFichier.txt") 'indique le chemin vers le fichier texte.
    
                MyReader.TextFieldType = FileIO.FieldType.Delimited
                MyReader.SetDelimiters(" ") 'définit le (ou les) caractère qui délimite les chaines de caractères.
    
                Dim currentRow As String()
                While Not MyReader.EndOfData    'on lit le fichier jusqu'à la fin.
    
                    For j = 0 To 1  'relatif au nombre de colone du tableau (nbr-1)
    
                        currentRow = MyReader.ReadFields()  'compte le nombre de chaines de caractères délimitées pas des espaces contenues dans le fichier texte.
    
                        Dim y(1, currentRow.Length - 1) As String   'création du tableau à 2 colones et autant de lignes que de variables délimitées par un espace contenues dans le fichier texte.
    
                        For i = 0 To currentRow.Length - 1  'relatif au nombre de lignes du tableau (nbr-1)
                            y(j, i) = currentRow(i) 'on assigne la chaine de caractères dans les cases du tableau
                            Console.WriteLine("y(" & j & "," & i & ") = " & y(j, i))    'on lit le contenu du tableau
                        Next
    
                    Next
                End While
            End Using
            Console.Read()  'pause pour nous laisser le temps de lire le tableau
        End Sub
    
    End Module



    • Partager sur Facebook
    • Partager sur Twitter
      4 mars 2020 à 18:49:42

      Pourquoi ne pas vous inspirer de l'exemple dans la documentation officielle (MSDN) de la méthode "ReadFields ?

      https://docs.microsoft.com/fr-fr/dotnet/api/microsoft.visualbasic.fileio.textfieldparser.readfields?view=netframework-4.8#Microsoft_VisualBasic_FileIO_TextFieldParser_ReadFields

      (Merci pour cette classe que je ne connaissais pas ;))

      Elle gère un nombre quelconque de "colonne" et de "ligne".

      Pour vous simplifier la vie, dans un premier temps, je vous conseille de stocker les données dans une List(of List(of Double)).

      Pour la conversion d'une chaine de caractère de la forme "5.00000e+001" en un Double, je vous conseille la méthode ToDouble de la classe Converter

      https://docs.microsoft.com/en-us/dotnet/api/system.convert.todouble?view=netframework-4.8#System_Convert_ToDouble_System_String_System_IFormatProvider_

      Je référence la version demandant un "IFormatProvider" car le "." comme séparateur des décimales risque de poser des problèmes sur les machines "non US".

      • Partager sur Facebook
      • Partager sur Twitter
      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
        5 mars 2020 à 15:20:41

        Bonjour,
        Je n'avais pas trouvé cet exemple, mais après l'avoir regardé, je crois avoir fait quasiment la même chose, excepté dans la boucle et que je traite pas de cas d'erreur... :euh:

        Je viens de regarder pour stocker mes données dans une List(of List(of Double)) mais si je fais ça je ne peux pas stocker le nom des variables qui est une chaîne de caractère, si...?

        Pour la partie conversion j'ai réglé le problème en écrivant y(j, i) = currentRow(i).Replace(".", ",") dans ma boucle For. Je ne sais pas si c'est très académique mais dans mon cas ça marche et comme les variables de mon fichier d'entré auront toujours la même typographie ça ne devrait pas poser de problème...

        Je mets ce-dessous le code que j'ai modifier et qui désormais semble répondre à toutes mes exigences.

        Module Module1
        
            Sub Main()
                Dim i As Integer = 0    'déclaration et initialisation des compteurs.
                Dim j As Integer = 0    'déclaration et initialisation des compteurs.
                Dim y(1, 0) As String   'déclaration du tableau à 2 lines 1 colone qui viendra accueillir la ou les variables.
        
                Using MyReader As New Microsoft.VisualBasic.FileIO.TextFieldParser("C:\Users\Utilisateur\Documents\Visual Studio 2010\Projects\ConsoleApplication6\test.txt") 'indique le chemin vers le fichier texte.
        
                    MyReader.TextFieldType = FileIO.FieldType.Delimited
                    MyReader.SetDelimiters(" ") 'définit le (ou les) caractère qui délimite les chaines de caractères.
        
                    Dim currentRow As String()
        
                    While Not MyReader.EndOfData    'on lit le fichier jusqu'à la fin.
        
                        For j = 0 To 1  'relatif au nombre de colone du tableau (nbr-1)
        
                            currentRow = MyReader.ReadFields()  'compte le nombre de chaines de caractères délimitées pas des espaces contenues dans le fichier texte.
        
                            ReDim Preserve y(1, currentRow.Length - 1) 'redimentionnement du tableau à 2 colones et autant de lignes que de variables.
        
                            For i = 0 To currentRow.Length - 1  'relatif au nombre de lignes du tableau (nbr-1)
                                y(j, i) = currentRow(i).Replace(".", ",") 'on assigne la chaine de caractères dans les cases du tableau
                                Console.WriteLine("y(" & j & "," & i & ") = " & y(j, i))    'on lit le contenu du tableau
                            Next
        
                        Next
        
                    End While
        
                End Using
        
                'Console.ReadLine()  'pause pour nous laisser le temps de lire le tableau
                Console.WriteLine(y(0, 0) & y(0, 1) & y(0, 2) & y(1, 0) & y(1, 1) & y(1, 2))    'on lit le tableau en entier pour vérifier que tout a bien fonctionné
                Console.ReadLine()  'pause pour nous laisser le temps de lire le tableau
        
                '*Insérer la suite du programme en dessous*
        
            End Sub
        
        End Module



        • Partager sur Facebook
        • Partager sur Twitter
          5 mars 2020 à 16:16:19

          >, excepté dans la boucle et que je traite pas de cas d'erreur

          Eux, ils "traitent" un nombre variable de valeur par ligne "plus élégamment" (pas de "ReDim Preserve" tout cracra ni de "j" borné à 0-1).

          >mais si je fais ça je ne peux pas stocker le nom des variables

          De quel "nom" parlez-vous ? Et pour quoi faire ?

          Avec l'approche "List(of List(of Double))", vous faites d'abord une validation locale des formats, puis, vous avez toutes les informations pour une validation "globales" (nombre paire de valeurs, etc...). Le code sera beaucoup plus clair si vous n'essayez pas de faire tout en même temps.

          >Pour la partie conversion j'ai réglé le problème en écrivant

          Fausse bonne idée, votre tambouille ne gère pas les valeurs avec des délimiteurs de milliers, rend donc invalide des nombres qui sont valide à la base, rend aussi valide des nombres qui ne le sont pas à la base, c'est pas correctement généralisable, etc...

          Et tout ça pour ne pas utiliser correctement une API qui fait tout le boulot, c'est vraiment nimportnawak.

          >Je ne sais pas si c'est très académique

          C'est surtout très pourri.

          >mais dans mon cas ça marche

          Ça marchera jusqu'au pire moment pour que cela déconne (cf. loi de Murphy).

          Vous avez les fonctions pour, utilisez-les, bordel !

          >les variables de mon fichier d'entré auront toujours la même typographie

          Parce qu'il n'y aura jamais d'update et que j'ai testé tous les cas et configuration possible. Ouais, et les marmottes, elles mettent le chocolat dans le papier d'alu.

          >ça ne devrait pas poser de problème...

          Toi, tu connais pas assez Murphy.

          Vous avez les fonctions pour, utilisez-les, bordel !(BIS)

          • Partager sur Facebook
          • Partager sur Twitter
          Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
            6 mars 2020 à 19:50:03

            Bonjour,

            Ça ne valait peut-être pas la peine d’être désagréable dans votre message... ! Je n’avais jamais touché une ligne de VB.NET avant cette semaine, vous me pardonnerez donc mes erreurs et ma méconnaissance des API et autres fonctionnalités.

            > Eux, ils "traitent" un nombre variable de valeur par ligne "plus élégamment"
            Je ne vois pas en quoi c’est plus élégant puisqu’ils ne font pas la même chose que moi. Dans leur exemple (si j’ai bien compris…) ils se content de recopier ligne par ligne, et non bout de ligne par bout de ligne, le contenu d’un fichier dans un autre. Moi ce n’est pas ce que je souhaite faire.
            A moins que j’ai mal compris le fonctionnement de leur code, ce qui est tout à fait possible, mais dans ce cas merci de me l’expliquer au lieu d’être sarcastique.

            > De quel "nom" parlez-vous ?
            Je parle de la seconde ligne du fichier .txt (cf. premier message), j’ai besoin de ces noms car dans la suite du programme je ferai appel à des fonctions mathématique (Coef1*Coef2+Coef3 par exemple) et il est plus commode de les écrire avec le nom des coefficients qu’avec des éléments de listes indicées.

            > vous faites d'abord une validation locale des formats, puis, vous avez toutes les informations pour une validation "globales"…
            Que voulez-vous dire par là exactement ? Je ne comprends pas cette histoire de validation locale puis globale…

            > votre tambouille ne gère pas les valeurs avec des délimiteurs de milliers…
            Les variables de mon fichier d’entré auront toujours la même typographie, car le logiciel qui le génère écrit les valeurs en écriture scientifique, il n’y a donc pas de séparateur des milliers ni d’autre chose. Ils seront toujours écrits sous la forme 1.23456789e+012 ou 1.23456789e-012 indépendamment de ce que l’utilisateur écrit, et si erreur de saisie il doit y avoir, elles seront gérées par LS-OPT et non par mon programme.

            > Vous avez les fonctions pour, utilisez-les, bordel !
            En plus de ne pas être au courant de leur existence, peut-être que si les néophytes comme moi n’utilisent pas tel ou tel fonction c’est aussi parce qu’ils ne comprennent pas comment les utiliser, éventuellement hein… ! Du coup ce serait peut-être plus formateur pour tout le monde de proposer une fonction et d’expliquer un peu comment elle fonctionne.

            > Parce qu'il n'y aura jamais d'update et que j'ai testé tous les cas et configuration possible.
            Les variables de mon fichier d’entré auront toujours la même typographie pour les raisons évoquées plus haut, mais aussi parce qu’il n’y aura pas d’update affectant cet aspect particulier du logiciel.

            Moi je ne demande qu’à apprendre en lisant les réponses des gens qui savent, à condition qu’ils soient respectueux et qu’ils sachent s’adapter au niveau technique de leur interlocuteur, sinon ça sert à rien.

            • Partager sur Facebook
            • Partager sur Twitter
              8 mars 2020 à 22:59:23

              Bon j'ai survolé la discussion et je ne suis pas certain qu'utiliser la classe TextFieldParser soit judicieux ou pertinent dans ce cas (en plus elle est pas forcément tip-top niveau perf mais c'est anecdotique)

              En l'état tu as un fichier de 2 lignes avec des valeurs séparées par des espaces. Si j'ai suivi on doit supposer le fichier bien formaté, donc il y a autant d'élément sur chaque ligne.

              Après, là c'est pas tout à fait clair, la première ligne contient les valeurs dans un format défini, mais j'ignore si dans le programme tu les veux en tant que texte (String) ou parsés comme numérique (Double ou Decimal). Quant à la seconde ligne elle contient les «noms des variables» associées aux valeurs.

              Du coup ce que je preconiserais, ça serait de lire le fichier ligne par ligne (File.ReadAllLines) ; splitter chacune sur l'espace (String.Split) ; parcourir ces tableaux en même temps (vu qu'ils doivent avoir le même nombre d'éléments) et alimenter un dictionnaire (Dictionary(Of String, String) ou Dictionary(Of String, Double) selon l'objectif) dont les clefs seront les noms (j'imagine que les noms sont uniques) et les valeurs, leur valeur associée (potentiellement parsées au besoin)

              Et sauf erreur, le tour est joué le job est fait.

              • Partager sur Facebook
              • Partager sur Twitter
              Censément, quelqu'un de sensé est censé s'exprimer sensément.
                9 mars 2020 à 14:48:55

                Bonjour,

                Oui, tu as très bien compris ce que je souhaitais faire, et pour ce qui la valeur numérique des variables, je souhaite bien l’utiliser en tant que double.

                Donc si j’ai bien compris ce que tu dis, il faut que je remplace toutes les lignes de : Using MyReader à : End Using
                par : File.ReadAllLines("C:\Users…) avec un String.Split et un Dictionary(Of String, Double) pour les valeurs numériques des variables et un Dictionary(Of String, String) pour le nom des variables… !?

                Cependant, comment dois-je utiliser File.ReadAllLines ? Car je présume qu’il faut stocker ce que cette ligne lit du fichier dans une variable. J’ai donc essayé ceci :
                Dim LIGNE As String ‘ou un autre type
                LIGNE = File.ReadAllLines("C:\Users…
                Mais ça ne fonctionne pas (la console m’affiche « System.String[] » à la place du contenu du fichier, sans aide ni information supplémentaire).
                Du coup pour voir d’où pouvait venir le problème, j’ai essayé avec File.ReadAllText et là ça marche bien (mais évidemment ça lit tout en un seul bloc ce n’est pas ce dont j’ai besoin) mais ça ne m’a pas avancé dans la résolution de mon souci ^^
                Du coup, je ne vois pas bien comment utiliser cette commande. Pourrais-tu me détailler d’avantage son utilisation s’il-te plaît ?
                • Partager sur Facebook
                • Partager sur Twitter
                  10 mars 2020 à 2:07:18

                  Pour savoir comment s'utilise une classe/méthode la documentation c'est assez utile...

                  Après si t'arrives à récupérer dans un string le résultat d'une méthode qui renvoie un tableau de strings c'est que tu dois pas avoir activer l'option Strict ; c'est la porte ouverte à pas mal de soucis...

                  Pour le reste je vais être sympa (ou j'ai juste la flemme de faire de longues explications) ...

                  Sub Main()
                      Dim lines() As String = File.ReadAllLines("C:\Users\Utilisateur\Documents\Visual Studio 2010\Projects\ConsoleApplication6\test.txt")
                  
                      Debug.Assert(lines.Length = 2) ' ça peut pas faire de mal
                  
                      Dim rawValues() As String = lines(0).Split(" "c)
                      Dim names() As String = lines(1).Split(" "c)
                  
                      Debug.Assert(rawValues.Length = names.Length) ' idem ici
                  
                      Dim dict As New Dictionary(Of String, Double)(names.Length)
                  
                      For i As Integer = 0 To names.Length - 1
                          dict.Add(names(i), Double.Parse(rawValues(i))) ' Parse à adapter au besoin (ParseExact, format etc.)
                      Next
                  
                      ' Affichage (verif)
                      For Each entry As KeyValuePair(Of String, Double) In dict
                          Console.WriteLine("{0} : {1}", entry.Key, entry.Value)
                      Next
                  End Sub

                  (Aux potentielles erreurs près, je tape directement ici sans avoir testé le truc)

                  • Partager sur Facebook
                  • Partager sur Twitter
                  Censément, quelqu'un de sensé est censé s'exprimer sensément.

                  [VB.NET] Réutiliser les variables d'un .txt

                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                  • Editeur
                  • Markdown