Problème : extraire données d'un fichier sequentiel

Résolu
Moundir76 Messages postés 281 Date d'inscription dimanche 3 octobre 2010 Statut Membre Dernière intervention 16 mai 2014 - 26 mai 2011 à 09:35
cs_ShayW Messages postés 3253 Date d'inscription jeudi 26 novembre 2009 Statut Membre Dernière intervention 3 décembre 2019 - 26 mai 2011 à 16:18
Bonjour,

J'ai a ma disposition un fichier texte dans lequel sont référencés des articles. A chaque ligne correspond un article. J'ai la structure de tous les champs. Je m'explique : je sais par exemple que sur chaque ligne, de la position 2 à la position 3, j'ai une lettre correspondant a l'article, et de la position 200 à 210 j'ai le prix. Je connais aussi la structure de tous les autres champs mais ils ne me sont pas nécessaires. Je cherche juste a extraire quelques infos pour chaque ligne de produit et tout mettre dans un tableau tel que

A | 200
D | 300
E | 400


J'utilise visual basic, après de nombreuses recherches, j'ai trouvé un code :

Dim T() as string
...
Open "C:\Monfichier.txt" As #1 For Input
i = -1
While Not Eof(1)
  i = i + 1
  Redim Preserve T(i)
  Line Input #1, T(i)



Cependant, visual studio ne connais pas "open", j'ai donc opté pour :

Dim i As Integer
        Dim T(i) As String


        My.Computer.FileSystem.OpenTextFileReader("C\catalogue.txt")
        i = -1
        While Not EOF(1)
            i = i + 1
            ReDim Preserve (i)
            LineInput(1), T(i)

        End While


Mais VB m'indique : "Erreur 1 Les instructions 'ReDim' requièrent une liste entre parenthèses des nouvelles limites de chaque dimension du tableau. "


Auriez vous une idée ou une solution qui pourrait m'expliquer ou est mon erreur et comment pourrais je exploiter ce fichier ??

Cordialement,

27 réponses

cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
26 mai 2011 à 10:31
Je crois que y'a un mélange entre les deux méthodes de lecture de fichier.
Dans la 2ème méthode il ne faut pas un LineInput, mais un ReadLine()
Voilà à quoi peut ressembler ton code :

Dim T() As String
Dim i As Integer
Dim sr As StreamReader 
Dim ligne As String
sr = my.Computer.FileSystem.OpenTextFileReader("C\catalogue.txt")
i = 0
Do
ligne = sr.ReadLine()
If (Not ligne Is Nothing) Then
i = i +1
Redim Preserve T(i)
T(i) = ligne
End If
Loop Until ligne Is Nothing
sr.Close()


A noter :
- pas de gestion d'exception dans ce code, je te laisse le faire
- j'initialise i à 0 car il me semble que les indices commence à 1 en VB, et qu'un Redim Preserve T(0) doit pas enchanter le compilo ^^
- je suis pas expert VB, une méthode plus classieuse existe peut-être
3
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
26 mai 2011 à 10:45
oki,

dans l'absolu je ferai une classe de mapping (et oui, encore ^^)

Tu crées une simple classe avec les champs qui te vont bien (label et quantity a priori), et tu lui mets un constructeur qui prend ses valeurs en paramètre.

Ensuite tu remplace ton tableau de String par un tableau de ce nouvel objet.

Enfin, dans ta boucle, au lieu de faire :
 T(i) = ligne

tu fais :
 T(i) = New MonObjetDeMapping(Mid(ligne, 2, 2), Mid(ligne, 200, 11))


C'est sûrement la méthode que j'aurais choisi mais tu peux aussi :
- faire des tableau 2D (n, m) avec m constante correspondant aux nombre de champs,
- faire autant de tableau que tu as de champs à traiter
3
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
26 mai 2011 à 11:40
Pourquoi pas effectivement faire le traitement en aval.
Est-ce que c'est optimisé ? non
Est-ce que la différence sera sensible ? je pense pas, donc pas de souci

Sinon avec ma technique d'objet ça donnerait un truc comac :

Code de la classe de mapping :
Public Class Product
' les champs extraits
Public Reference As String
Public Price As Double
'le constructeur paramétré
Sub New(ByVal pref As String, ByVal pprice As Double)
Me.Reference = pref
Me.Price =  pprice
End Sub
End Class


Code de l'extraction des données :
Dim T() As Product
Dim i As Integer
Dim sr As StreamReader
Dim ligne As String
sr  = My.Computer.FileSystem.OpenTextFileReader("C\catalogue.txt")
i = 0
Do
ligne = sr.ReadLine()
If (Not ligne Is Nothing) Then
i = i + 1
ReDim Preserve T(i)
T(i) = New Product(Mid(ligne, 2, 2), Convert.ToDouble(Mid(ligne, 200, 11)))
End If
Loop Until ligne Is Nothing
sr.Close()
3
cs_ShayW Messages postés 3253 Date d'inscription jeudi 26 novembre 2009 Statut Membre Dernière intervention 3 décembre 2019 57
26 mai 2011 à 13:40
Voila une autre proposition
il faut tester
Private Structure lesdetails
     Public article As Char
     Public prix As Double
End Structure
Private listdetails As New List(Of lesdetails)
Private listitems As New List(Of String)
Private Sub ReadFile()
   Dim pathfichier As String
  'le chemin du fichier
   pathfichier = "C:\ReadFile\TEST.TXT"
   Try
       listitems = System.IO.File.ReadAllLines(pathfichier).ToList
   Catch ex As Exception
      MessageBox.Show(ex.Message)
  End Try
End Sub

Private Sub ExtraireDetails()
   Dim detail As lesdetails
   listdetails.Clear()
   For Each element In listitems
       
       detail.article = element.Substring(2, 1)
       detail.prix = element.Substring(200, 11)
       listdetails.Add(detail)
    Next
 End Sub
3

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

Posez votre question
cs_ShayW Messages postés 3253 Date d'inscription jeudi 26 novembre 2009 Statut Membre Dernière intervention 3 décembre 2019 57
26 mai 2011 à 15:46
tout d'abord
dans un tableau les position commence par 0
la list est comme un tableau
tu peux t'addresser par index
list(0)
quand je lis ton fichier il est mis
dans listitems qui se comporte comme un tableau de chaine
listitems(0) la premiere ligne de ton fichier
Dim ch As Char
'dans ch j'ai le premier caractère de la premiere de ton fichier
ch = listitems(0)(0)

par ex je met les deux list dans une listbox nommée listX
ListX.Items.Clear()
        Dim str As String
        For iter As Integer = 0 To listdetails.Count - 1
            str = listitems(iter).Substring(1, 1) & " " _
            & listitems(iter).Substring(199, 11) & listdetails(iter).article & " | " & listdetails(iter).prix
            ListX.Items.Add(str)
        Next

j'espère avoir mieux expliqué

et aussi en net
VB 6 Commands and equivalents in net
Len = .Length
Mid = .SubString
Replace = .Replace
InStr = .IndexOf
UCase = .ToUpper
LCase = .ToLower
Split = .Split
Join = .Join
3
cs_ShayW Messages postés 3253 Date d'inscription jeudi 26 novembre 2009 Statut Membre Dernière intervention 3 décembre 2019 57
26 mai 2011 à 16:18
Attention
ne pas utiliser un messagebox dans une loop

bonne prog
3
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
26 mai 2011 à 10:07
Salut,

dans le 2ème code que tu as retranscrit il manque le nom de ton tableau
ton code : ReDim Preserve (i)
ce qu'il faut : ReDim Preserve T(i)

le souci vient ptèt de là
0
Moundir76 Messages postés 281 Date d'inscription dimanche 3 octobre 2010 Statut Membre Dernière intervention 16 mai 2014
26 mai 2011 à 10:12
Merci jopop de cette réponse rapide, en effet il manquait bien le nom du tableau, cependant quand j'essaye d'inserer la ligne dans un tableau avec : "LineInput(1, T(i))"

VB me dit "Arguments trop nombreux pour "Public Function LineInput(FileNumber as Integer) as string""

J'ai beau chercher sur le MSDN je ne trouve rien ...
0
Moundir76 Messages postés 281 Date d'inscription dimanche 3 octobre 2010 Statut Membre Dernière intervention 16 mai 2014
26 mai 2011 à 10:25
EDIT : Problème résolu,

Désormais je recupere -chaque ligne dans une variable. Je souhaite a partir d'autres variables extraire les données qui m'interessent. Ex reference = Strings.Mid(TextLine, 10, 20).

Cela ne me pose pas de souci mais je n'arrive pas a mettre ces données dans un tableau comme expliqué dans mon premier message...


Merci d'avance
0
Moundir76 Messages postés 281 Date d'inscription dimanche 3 octobre 2010 Statut Membre Dernière intervention 16 mai 2014
26 mai 2011 à 10:57
Merci pour tes réponses astucieuses, Je suis débutant dans le VB et je n'ai pas encore attaqué la programmation orientée objet.
Mais je pense qu'en créant un tableau 2D je vais réussir.
Le seul hic c'est que je ne vois pas comment je peux ajouter dans un tableau T( , ) d'une part X et d'une autre part Y

Ligne 1 du tableau => X | Y

J'opterais pour (Mid(ligne, 2, 2), Mid(ligne, 200, 11))

Mais je ne vois pas comment VB fait la différence entre X et Y dans le tableau pour la meme ligne !

Encore Merci Jopop
0
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
26 mai 2011 à 11:06
Si on veut représenter les cells d'un tableau ça donnerait plutôt un truc comac :
X1Y1 | X1Y2
X2Y1 | X2Y2
X3Y1 | X3Y2
...

Par contre je viens de voir qu'apparemment en VB on ne peut redimensionner un tableau que sur sa dernière dimension. Du coup il faut voir la chose comac :
X1Y1 X1Y2 X1Y3
--- --- --- ...
X2Y1 X2Y2 X2Y3

Sinon j'ai trouvé sur ce site un topic sur les tableaux VB qui pourrait t'intéresser
0
Moundir76 Messages postés 281 Date d'inscription dimanche 3 octobre 2010 Statut Membre Dernière intervention 16 mai 2014
26 mai 2011 à 11:17
Merci pour l'explication et le lien, mais je ne comprends pas sur le topic, je suis en train de réfléchir et de me dire si je ne suis pas mieux à mettre dans mon tableau à une seule dimension la concaténation des infos qui m'interessent puisque les champs ont toujours la même longueur.

x1 => A 200
x2 => D 300
...........

Je ne sais pas si c'est tres optimisé, car par la suite je vais devoir aller extraire chaque lettre et la comparer a une base de données afin d'inserer le prix de l'article correspondant directement dans la BDD...

Merci !
0
Moundir76 Messages postés 281 Date d'inscription dimanche 3 octobre 2010 Statut Membre Dernière intervention 16 mai 2014
26 mai 2011 à 11:56
Merci, cette méthode fonctionne aussi mais je n'arrive pas a interpreter comment sont stockées les données ... Est ce que VB va sélectionner l'article puis le prix et les concatener dans le tableau ou bien est ce que le tableau est séparé en 2 categories distinctes dans une seule ligne ???

Je ne comprends pas comment je peux exploiter ces données... Pour ma part j'avais vu ça comme ca :

Dim T() As String
        Dim i As Integer
        Dim sr As StreamReader
        Dim ligne As String
        sr = My.Computer.FileSystem.OpenTextFileReader("C:\catalogue.txt")
         i = 1
        Do
        ligne = sr.ReadLine()
        
        
             If (Not ligne Is Nothing) Then
                  i = i + 1
                   ReDim Preserve T(i)
                    T(i) = Mid(ligne, 64, 12) + Mid(ligne, 198, 11)
                                      End If
               Loop Until ligne Is Nothing
                sr.Close()


Ainsi sur chaque indice de tableau on trouvait : T(1) = A 200
etc...

Peux tu m'expliquer la différence avec ta méthode ?
0
cs_jopop Messages postés 1540 Date d'inscription lundi 26 mai 2003 Statut Membre Dernière intervention 1 août 2013 12
26 mai 2011 à 12:05
Voilà comment accéder à tes données après les avoir extraites selon ma méthode :
'affiche le nom du 1er produit dans une popup, soit "A"
MsgBox (T(1).Reference)
'affiche le prix du 1er produit dans une popup, soit 200
MsgBox (T(1).Price)


La différence est simple : tu fais un tableau de string et chaque fois que tu vas vouloir une info en particulier il faudra découper cette string. Ma méthode fait le découpage en amont, tu n'auras plus besoin de le faire par la suite.

NB : Attention, je crois que l'opérateur de concaténation en VB est le '&' (et non le '+' comme en C# ou JS)
0
cs_ShayW Messages postés 3253 Date d'inscription jeudi 26 novembre 2009 Statut Membre Dernière intervention 3 décembre 2019 57
26 mai 2011 à 13:06
Salut
pas clair
quand tu dis
je sais par exemple que sur chaque ligne, de la position 2 à la position 3, j'ai une lettre correspondant

2 à 3 il y a deux caractères
et aussi as tu la position 0 ?
0
Moundir76 Messages postés 281 Date d'inscription dimanche 3 octobre 2010 Statut Membre Dernière intervention 16 mai 2014
26 mai 2011 à 13:40
En effet Jopop ta méthode me parait plus simple et optimisée pour ma recherche de données. Merci beaucoup. et sous VB pour concatener c'est bien "+" ;).

@ShayW

Pour être plus précis quand j'ai par exemple :

"A","1235                            ",


A la position 1 je suis avant mon premier guillemet. et donc entre la position 2 et la position 3 j'obtiens bien A
0
cs_ShayW Messages postés 3253 Date d'inscription jeudi 26 novembre 2009 Statut Membre Dernière intervention 3 décembre 2019 57
26 mai 2011 à 13:53
plutot

  Private Structure lesdetails
     Public article As Char
     Public prix As Double
End Structure
Private listdetails As New List(Of lesdetails)
Private listitems As New List(Of String)
Private Sub ReadFile()
   Dim pathfichier As String
  'le chemin du fichier
   pathfichier = "C:\ReadFile\TEST.TXT"
   Try
       listitems = System.IO.File.ReadAllLines(pathfichier).ToList
   Catch ex As Exception
      MessageBox.Show(ex.Message)
  End Try
End Sub

Private Sub ExtraireDetails()
   Dim detail As lesdetails
   listdetails.Clear()
   For Each element In listitems
       
       detail.article = element.Substring(1, 1)
       detail.prix = element.Substring(199, 11)
       listdetails.Add(detail)
    Next
 End Sub                       
0
Moundir76 Messages postés 281 Date d'inscription dimanche 3 octobre 2010 Statut Membre Dernière intervention 16 mai 2014
26 mai 2011 à 14:08
Merci ShayW,

Ce que je comprends : Un procédure va lire le fichier afin de le mettre dans une "list" et une autre procédure va extraire de la liste uniquement les données qui m'interessent.
J'execute donc ces 2 procédures dans ma private sub load mais cependant je n'arrive pas a acceder a cette "listdetails" .......... Je ne comprends pâs sous quelle forme est stockée cette "list".

Merci
0
cs_ShayW Messages postés 3253 Date d'inscription jeudi 26 novembre 2009 Statut Membre Dernière intervention 3 décembre 2019 57
26 mai 2011 à 14:24
comme tu as dis
ReadFile lis tout le fichier d'un bloc
et le met dans une list of string

que veux tu faire avec listdetais ?
pour accéder à chaque élement de listdetails

for each element as lesdetails in  listdetails
'que veux tu faire exactement ?
  element.article
  element.prix
next
0
Moundir76 Messages postés 281 Date d'inscription dimanche 3 octobre 2010 Statut Membre Dernière intervention 16 mai 2014
26 mai 2011 à 14:35
En fait je souhaite afficher les resultats de la list element afin de verifier que tout y est. Sinon je ne comprends pas comment ils sont triés dans la liste. Par exemple je vais prendre chaque référence pour la comparer a une BDD SQL.

Exemple : A l'emplacement 1 ( Dans le cas du tableau T(1)=A) je voudrais trouver la valeur A et parcourir valeur par valeur cette liste.

Merci pour ton aide
0
Rejoignez-nous