Importation fichier CSV et stockage des données

Résolu
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012 - 13 juin 2011 à 19:33
CGSI3 Messages postés 416 Date d'inscription vendredi 22 février 2008 Statut Membre Dernière intervention 7 janvier 2018 - 15 juin 2011 à 23:26
Bonjour,

Je suis nouveau dans le monde de .NET et je veux bien chercher par moi même mais là j'en ai marre... Après avoir parcouru tous les forum possibles, je n'ai toujours pas trouvé de réponse à mes questions!

Premièrement, j'utilise VB.NET 2005. Dans mon soft, je dois charger des données depuis des fichiers CSV. J'ai environ compris comment lire un fichier CSV mais ma première question est la suivante:

- Quel moyen, d'après vous, est le plus simple et le plus rapide pour stocker ces données pour ensuite les utiliser dans le programme? Petite précision, je n'ai pas besoin de retrouver ces données après avoir quitté le logiciel (donc pas forcément envie de les enregistrer dans une base de données).

J'ai essayer de travailler avec des tableaux mais travailler avec un tableau 2D me semble impossible!! Car impossible de trouver comment copier un simple tableau dans un tableau 2D (par exemple après avoir lu et découpé une ligne du fichier CSV on obtient un tableau simple que j'aimerais copier dans un 2D). De plus mon fichier CSV contient 100 colonnes et un nombre de ligne très important qui peut varier.

Je vous serais très reconnaissant si vous pouviez m'aider, là je sèche complètement!

20 réponses

Mayzz Messages postés 2813 Date d'inscription mardi 15 avril 2003 Statut Membre Dernière intervention 2 juin 2020 28
15 juin 2011 à 22:46
Ah la je comprend mieux =)

J'étais partis du principe inverse, que tu voulais stocker une valeur dans un tableau et pourvoir la retrouver via X et Y, en gros : MonTableau(X, Y). Je ne sais pas pourquoi en fait je me suis mélangé les pédales à bien regarder tes explications j'aurais du comprendre. Bref, j'ai capté c'est le principal j'ai donc été voir ton code en amont et en effet il ne peut fonctionner. Car un tableau 2D doit avoir sa première dimension définie à l'avance, en l'occurrence la seconde tu la connais c'est 100, à moins qu'elle ne soit pas fixe mais cela m'étonnerais. Du coup cela oblige à charger le fichier complet en mémoire dans une variable ou alors de lire celui-ci ligne par ligne pour en connaitre le nombre. En suite tu pourras déclarer ton tableau comme suit :

Dim MonTab2D(NbLine-1, 99) As String

Il te faut donc obligatoirement lire le fichier en entier avant de le stocker, c'est un peu naze mais c'est comme ça.

Il existe l'instruction Redim (Redim Preserve) mais elle n'est valable que pour la dimension la plus à droite, il te faut donc fixer la 1ère dimension lors de la déclaration du tableau on reste au même point stocker le fichier en mémoire et ce n'est pas très propre ou lire deux fois le fichier, une fois pour connaitre le nombre de ligne et une autre fois pour stocker.

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
2
Mayzz Messages postés 2813 Date d'inscription mardi 15 avril 2003 Statut Membre Dernière intervention 2 juin 2020 28
15 juin 2011 à 23:06
Ah oui ok tu lis le fichier en entier. Je pensais que tu étais contre =)


Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
1
CGSI3 Messages postés 416 Date d'inscription vendredi 22 février 2008 Statut Membre Dernière intervention 7 janvier 2018 1
15 juin 2011 à 23:26
Bonsoir a tous les deux,
Juste un bémol a la fonction Split
Ce genre de ligne est normalement valable dans un fichier CSV,
"01DB","BIBOST","yves","Resp Achats","200 CH DES ORMEAUX",,"LIMONEST",69578," 04.78.66.37,74","04,78,66,34,95","yves.bibost@01db.com", ....

Le second numéro de téléphone ne peut donc être extrait correctement ...
Bonne soirée CGSI3
1
CGSI3 Messages postés 416 Date d'inscription vendredi 22 février 2008 Statut Membre Dernière intervention 7 janvier 2018 1
13 juin 2011 à 20:57
Bonsoir,
Voici un exemple rapide, il est surement a améliorer mais il
te montre comment travailler avec une liste d'array (String)
Le séparateur est a vérifier.

Imports System.IO

Dim lines As String() = File.ReadAllLines("c:\.... .csv", System.Text.Encoding.Default)
Dim Tab As New List(Of String)
Dim Tab2 As New List(Of Array)
Tab = lines.ToList
For Each line In Tab
Dim A As String()
A = line.Split(CChar(","))
Tab2.Add(A)
Next
MsgBox(Tab2.Item(1)(2))

Bonne Soirée CGSI3
0

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

Posez votre question
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012
13 juin 2011 à 21:08
Merci de la réponse.

Mais la encore, il y a des conflits entre les types des variables, ce qui me rend fou depuis ce matin! Les "commandes" .ToList et .Split ne peuvent pas être utilisées sur des variables de type array comme l'est la variable lines... J'ai fait que ça aujourd'hui et je m'arrache les cheveux
0
CGSI3 Messages postés 416 Date d'inscription vendredi 22 février 2008 Statut Membre Dernière intervention 7 janvier 2018 1
13 juin 2011 à 21:37
Je ne peux te proposer que cela.
J'ai juste 2 précisions:
Pour un tri en ligne tu dispose de cette manière de la méthode Sort
Tab2.Sort()
Mais il te faut chercher sur quel critere effectuer ce tri ???

et si tu met cette dernière ligne
Tab2.ToArray()
tu peux utiliser ton tableau de cette manière
MsgBox( Tab2(1)(2) )
C'est tout de même assez semblable a un tableau 2D
Que veux tu en faire exactement ensuite ?
0
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012
13 juin 2011 à 21:44
En fait j'aimerais importer les données du fichier CSV dans mon logiciel pour ensuite les utiliser pour tracer des graphes (ZedGraph), modifier mon interface graphique, faire des calculs, etc. Donc pour moi une méthode aurait été de charger les données dans un tableau 2D pour ensuite les retrouver facilement en sachant que la colonne n correspond aux datas n, etc.
Donc s'il existe une méthode plus simple pour travailler avec ces données, je suis ouvert!
0
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012
13 juin 2011 à 21:57
J'avais pensé faire qqch du style, mais cela ne fonctionne pas:

If System.IO.File.Exists(CSV_File) Then
Try
Dim sr As StreamReader = New StreamReader(CSV_File, System.Text.Encoding.Default)

While Not sr.EndOfStream()
CSV_Line = sr.ReadLine()
CSV_Data = Split(CSV_Line, ",")
For j 0 To j UBound(CSV_Data)
CSV_String(i, j) = CSV_Data(j)
Next
j += 1
End While

sr.Close()

Il y a conflit lorsque je veux copier mon tableau CSV_Data dans une ligne du tableau 2D CSB_String...

Merci encore de votre aide
0
CGSI3 Messages postés 416 Date d'inscription vendredi 22 février 2008 Statut Membre Dernière intervention 7 janvier 2018 1
13 juin 2011 à 21:59
Je seche ... il ne reste que l'utilisation de boucles entre 2 structures pour échanger les valeurs ...
J'ai actuellement le même genre de pb avec une base access ou je dois passer par un datagridview pour récupérer une table 2D
... Bon courage et Bonne soirée a toi CGSI3
0
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012
13 juin 2011 à 22:00
Oups comme vous l'aurai remarqué, c'est bien i += 1 et non j += 1 . Mais le problème n'est pas là.
0
CGSI3 Messages postés 416 Date d'inscription vendredi 22 février 2008 Statut Membre Dernière intervention 7 janvier 2018 1
13 juin 2011 à 22:32
Je me suis essayé avec ce code mais cela ne marche pas avec cette ligne, ce qui est normal ...

"01DB","BIBOST","yves","Resp Achats","200 CH DES ORMEAUX",,"LIMONEST",69578," 04.78.66.37,74","04,78,66,34,95","yves.bibost@01db.com",

Dim lines As String() = File.ReadAllLines("c:\... .csv", System.Text.Encoding.Default)
Dim B As String() = lines(0).Split(CChar(","))
Dim P(,) As String
ReDim P(lines.Count, B.Count)
Dim cpt As Integer
For cpt = 0 To lines.Count - 1
   Dim A As String()
   A = lines(cpt).Split(CChar(","))
   For cp2 = 0 To A.Count - 1
      P(cpt, cp2) = A(cp2)
   Next
Next
0
Mayzz Messages postés 2813 Date d'inscription mardi 15 avril 2003 Statut Membre Dernière intervention 2 juin 2020 28
13 juin 2011 à 23:25
Tu peux simplement utiliser la sérialisation binaire.

Il suffit de créer un classe sérialisable et une collection de cette classe :

Imports System.Runtime.Serialization.Formatters.Binary

<Serializable()> _
Public Class CoordinateCollection
    Inherits List(Of Coordinate)
    Public Function Save(ByVal targetFile As String) As Boolean
        Dim outStream As IO.Stream = Nothing
        Try
            If IO.File.Exists(targetFile) Then
                IO.File.Delete(targetFile)
            End If
            outStream = IO.File.Create(targetFile)
            Dim serializer As New BinaryFormatter
            serializer.Serialize(outStream, Me)
            Return True
        Catch ex As Exception
            Return False
        Finally
            If outStream IsNot Nothing Then
                outStream.Close()
                outStream.Dispose()
            End If
        End Try
    End Function
    Public Shared Function LoadFromFile(ByVal filename As String) As CoordinateCollection
        Dim inputStream As IO.Stream = Nothing
        Dim instance As CoordinateCollection = Nothing
        Try
            inputStream = IO.File.OpenRead(filename)
            Dim deserializer As New BinaryFormatter()
            instance = DirectCast(deserializer.Deserialize(inputStream), CoordinateCollection)
        Catch ex As Exception
        Finally
            If inputStream IsNot Nothing Then
                inputStream.Close()
                inputStream.Dispose()
            End If
        End Try
        Return instance
    End Function
    Public Function Clone() As CoordinateCollection
        Dim Instance As New CoordinateCollection
        For Each Item As Coordinate In Me
            Instance.Add(Item.Clone)
        Next
        Return Instance
    End Function
End Class
<Serializable()> _
Public Class Coordinate
    '
    Private _X As Double = 0
    Private _Y As Double = 0
    '
    Public Property X As Double
        Get
            Return _X
        End Get
        Set(value As Double)
            _X = value
        End Set
    End Property
    Public Property Y As Double
        Get
            Return _Y
        End Get
        Set(value As Double)
            _Y = value
        End Set
    End Property
    '
    Public Function Clone() As Coordinate
        Return Me.MemberwiseClone
    End Function
    Sub New()
    End Sub
    Sub New(X As Double, Y As Double)
        _X X : _Y Y
    End Sub
    '
End Class


En suite tu t'en sers comme cela :

    'Pour charger la collection depuis un fichier
    Dim Coordinates As New CoordinateCollection
    Coordinates = CoordinateCollection.LoadFromFile("chemindufichier")

    'Pour ajouter des données
    Coordinates.Add(New Coordinate(10, 100))

    'Pour enregistrer la collection
    Coordinates.Save("chemindufichier")

    'Puis pour lire
    For Each Item As Coordinate In Coordinates
        Debug.Print("X " & Item.X & "; Y " & Item.Y)
    Next


Il y a plus simple aussi créer un paramètre d'application de type collection mais c'est un peu moins souple.

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
0
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012
14 juin 2011 à 22:48
Hello Mayzz,
merci bien mais je vois pas vraiment comment ce bout de code peut récupérer les données d'un fichier CSV et surtout comment je pourrais ré-utiliser ces données dans mon logiciel en prenant par exemple la colonne X depuis la ligne Y jusqu'à la ligne Z, etc...
0
Mayzz Messages postés 2813 Date d'inscription mardi 15 avril 2003 Statut Membre Dernière intervention 2 juin 2020 28
14 juin 2011 à 23:54
Ok, je viens de te relire, en effet je t'ai mal compris. Ca m'arrive parfois ^^ Ne tiens pas compte de ma réponse du coup comme t'as surement pu le voir elle est hors propos.

Par contre avant de te répondre j'aimerais avoir plus de précisions. Pourquoi un tableau à deux dimensions ? Comment par la suite vas-tu interroger ton tableau ? Puisse qu'à la base tu obtiens juste une liste de coordonnées X/Y si je comprends bien ? Donc ton tableaux doit être d'une seule dimention mais chaque valeur doit être double. Car sinon je ne vois pas vraiment comment tu veux ranger une liste de point dans un tabeleau à deux dimensions...

Tu devrais plutôt faire une liste de point.

Dim MonTableau As New List(of Point)
MonTableau.Add(New Point(X,Y))

Dim Coordinate As Point = MonTableau(0)
Coordinate.X
Coordinate.Y

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
0
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012
15 juin 2011 à 21:09
Ben en fait mon fichier CSV contient 100 colonnes et un nombre de ligne très élevé (environ 13000). Chaque colonne correspond à un canal que je dois pouvoir sélectionner pour l'afficher sur un graphe, avec des axes x ou y paramètrables. Mais je dois aussi pouvoir sélectionner qu'une seule partie d'une colonne, suivant un tri que je mettrai en place, tri qui peut être lié avec les autres colonnes. Je dois avoir la possibilité d'afficher plusieurs canaux en même temps donc de sortir plusieurs colonnes. Vous comprenez?

Je dois aussi pouvoir utiliser ces données pour créer des canaux mathématiques donc plusieurs colonnes ensemble. Bref, s'il existe une méthode simple d'accéder à ces données facilement et rapidement ça m'arrangerait grandement.

Merci de votre aide
0
Mayzz Messages postés 2813 Date d'inscription mardi 15 avril 2003 Statut Membre Dernière intervention 2 juin 2020 28
15 juin 2011 à 21:24
En fait je t'avoue que je ne comprends pas trop. Pour moi je conçois les choses de façon à ce qu'une colonne ne représente qu'une valeur pour une ligne, en gros c'est une cellule, graphiquement on peu le représenter le tableau par une table Excel. Pour moi, une cellule ne contient qu'une valeur, soi X soit Y, mais pas les deux. Donc je ne comprends pas trop comment tu peux placer ta colonne sur un point 2D du graphique. Et je te repose donc la même question, si ton fichier comporte 13000 +- lignes et 100 colonnes alors pourquoi un tableau 2D ?

Par exemple si je prends une colonne d'un tableau (bidon), la suivante qui est une liste de valeurs :

Colonne A
25
14
34
55
14
45

Qu'est ce qui va déterminer les Axes X ou Y sur le graph ?

Désolé j'ai vraiment du mal à comprendre, ou alors il manque des informations...

Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
0
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012
15 juin 2011 à 21:48
Ben si on ouvre un fichier CSV avec Excel, ça donne bien un tableau en 2D, non?

avec ColonneA ColonneB ColonneC ColonneD ...
23 45 56 67
44 87 65 42
1 54 99 100
............
Bien sur qu'une cellule ne contient qu'une valeur. Mais dans la cellule d'un tableau MyTab en 2D, si on reprend le tableau ci-dessus, on a dans la case MyTab(0,0) la valeur 23, dans a case MyTab(2,3) = 100, ... Vous comprenez???

Dans un fichier CSV il y a des caractères
"adsa,sdAFFA,sdfaf,gheew,asgg"
"dfld,ztfsdf,tredd,utdfg,isvg"

Dans cet exemple, 2 lignes et 5 colonnes. C'est moi qui comprend rien ou j'explique si mal que ça?

Ensuite, pour faire mon graphe, je choisis par exemple de tracer les données de la colonne A en fonction de la colonne D.

Je vois pas comment être plus clair... désolé si j'explique mal, je suis fatigué ce soir ^^
0
Mayzz Messages postés 2813 Date d'inscription mardi 15 avril 2003 Statut Membre Dernière intervention 2 juin 2020 28
15 juin 2011 à 22:49
Ah ? Tu y es parvenu ? Je suis curieux de savoir comment tu stock sans déclarer à l'avance ?


Si le déboguage est l'art d'enlever les bogues, la programmation doit être l'art de les créer.
0
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012
15 juin 2011 à 22:54
Oui ça fonctionne parfaitement maintenant, manque plus qu'à supprimer les lignes vides et c'est super! En passant voici le code si ça intéresse qqun d'autre!
Merci de ta patience Mayzz

Public CSV_String(,) As String
Dim CSV_Data() As String
Dim i, j As Integer
Dim num_rows As Long
Dim num_cols As Long
Dim strline() As String


Public Sub Load_CSV(ByVal CSV_File As String)

If System.IO.File.Exists(CSV_File) Then
Try
Dim sr As StreamReader = File.OpenText(CSV_File)
CSV_Data = sr.ReadToEnd().Split(vbCrLf)
num_rows = UBound(CSV_Data)
strline = CSV_Data(0).Split(",")
num_cols = UBound(strline)
ReDim CSV_String(num_rows, num_cols)

' Copy the data into the array.
For i = 0 To num_rows - 1
strline = CSV_Data(i).Split(",")
For j = 0 To num_cols - 1
CSV_String(i, j) = strline(j)
Next
Next

sr.Close()
0
dudu1513 Messages postés 51 Date d'inscription jeudi 2 juin 2011 Statut Membre Dernière intervention 1 août 2012
15 juin 2011 à 22:42
Mais en fait je crois bien que j'ai trouvé! Mes soucis étaient ailleurs, je ne sais pas pourquoi mais mon fichier CSV était corrompu...

Je peux maintenant avoir toutes mes données dans mon tableau 2D!!!

Merci les gens pour votre patience
-1
Rejoignez-nous