Avatar billede SommerFyr Seniormester
27. juni 2016 - 19:25 Der er 45 kommentarer

Load af stor csv fil

Hej

Jeg er i den uheldig at min leverdør kun laver sin vareliste i en csv fil og da den er meget stor og jeg skal have den lave om til en xml fil eller nåde anden jeg kan søge i
Avatar billede arne_v Ekspert
27. juni 2016 - 19:35 #1
Kan data vaere i memory?

Ja => laes direkte ind fra CSV til en in-memory datastruktur og soeg i den.

Nej => load CSV ind i en database og soeg i denne.
Avatar billede SommerFyr Seniormester
27. juni 2016 - 19:40 #2
Hej arne_v

Jeg ved ikke om den kan være i memory da jeg pt load den via et script jeg kun finde
(http://planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=3636&lngWId=10) da jeg ikke lige kun finde nåde godt script til at load csv ind der var så stor..

Men ja min ide er også jeg vil have den over i nåde database eller xml er bare total på bar bund..
Avatar billede supertekst Ekspert
03. juli 2016 - 12:53 #3
Hvor stor er filen?
Avatar billede SommerFyr Seniormester
03. juli 2016 - 14:43 #4
Hej Den er godt og vel 30 mb. så ja vi taler om en rimelig stor csv fil jeg skal lave om til xml fil en gang i døgen..
Avatar billede supertekst Ekspert
03. juli 2016 - 15:28 #5
Ja - det er en pæn størrelse. Hvilket program skal anvendes til søgningen?
Avatar billede SommerFyr Seniormester
03. juli 2016 - 16:41 #6
Det skal bruges til en webshop i nåde vb.net
Avatar billede SommerFyr Seniormester
03. juli 2016 - 16:42 #7
forventer det bliver en webservice der engang i døgn henter csv fil og her skal den så lave den fra csv til xml.
Avatar billede supertekst Ekspert
03. juli 2016 - 17:32 #8
Ok..
Avatar billede arne_v Ekspert
04. juli 2016 - 02:16 #9
Det giver efter min bedste overbevisning ikke nogen mening at konvertere til XML. Du vinder ikke noget ved det.

Bare laes den ind i en List(Of DinDataKlasse) og soeg i den med LINQ.
Avatar billede SommerFyr Seniormester
04. juli 2016 - 02:56 #10
Hej Arne..

Nu er jeg ikke så stærk i .net enu. så jeg ville da blive glad hvis du kun give lidt mere hjælp gerne i form at en example da jeg er meget på bar bund.
Avatar billede arne_v Ekspert
04. juli 2016 - 04:25 #11
Her er et eksempel.

CSV fil:


1,"First line"
2,"One more"
3,"Again"
4,"More tricky with , in"


VB.NET kode:


Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Text

Namespace E
    Public Class Data
        Public Property Id As Integer
        Public Property Text As String
    End Class
    Public Class CSVReader
        Private stream As StreamReader
        Private fieldsep As Char
        Private strquote As Char
        Public Sub New(stream As StreamReader, fieldsep As Char, strquote As Char)
            Me.stream = stream
            Me.fieldsep = fieldsep
            Me.strquote = strquote
        End Sub
        Public Function ReadLine() As List(Of String)
            Dim line As String = stream.ReadLine()
            If line Is Nothing Then
                Return Nothing
            End If
            Dim res As New List(Of String)()
            Dim inq As Boolean = False
            Dim tmp As New StringBuilder("")
            For Each c As Char In line
                If c = fieldsep AndAlso Not inq Then
                    res.Add(tmp.ToString())
                    tmp = New StringBuilder("")
                ElseIf c = strquote Then
                    inq = Not inq
                Else
                    tmp.Append(c)
                End If
            Next
            res.Add(tmp.ToString())
            Return res
        End Function
        Public Function ReadLine(Of T As {Class, New})(ParamArray asgn As Action(Of String, T)()) As T
            Dim raw As List(Of String) = ReadLine()
            If raw Is Nothing Then
                Return Nothing
            End If
            Dim o As New T()
            For i As Integer = 0 To asgn.Length - 1
                asgn(i)(raw(i), o)
            Next
            Return o
        End Function
        Public Function ReadAllLines(Of T As {Class, New})(ParamArray asgn As Action(Of String, T)()) As List(Of T)
            Dim res As New List(Of T)()
            Dim o As T = ReadLine(asgn)
            While o IsNot Nothing
                res.Add(o)
                o = ReadLine(asgn)
            End While
            Return res
        End Function
        Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
            target = value
            Return value
        End Function
    End Class
    Public Class Program
        Public Shared Sub Main(args As String())
            Using sr As New StreamReader("C:\work\data.csv")
                Dim csv As New CSVReader(sr, ","C, """"C)
                Dim data As List(Of Data) = csv.ReadAllLines(Of Data)(
Sub(s, o)
    o.Id = Integer.Parse(s)
End Sub,
Sub(s, o)
    o.Text = s
End Sub
                )
                ' find the text for id 2
                Console.WriteLine(data.Find(Function(r) r.Id = 2).Text)
                ' find all id's where text contains a 'm' or 'M'
                For Each o As Data In data.Where(Function(r) r.Text.ToLower().Contains("m"C))
                    Console.WriteLine(o.Id)
                Next
            End Using
            Console.ReadKey()
        End Sub
    End Class
End Namespace


Output:


One more
2
4
Avatar billede SommerFyr Seniormester
04. juli 2016 - 15:49 #12
Hej Arne

Jeg har fåde dit eksempel til at virker men når jeg bruger min csv fil får jeg et par fejl

Min class

Imports System
Imports System.Collections.Generic
Imports System.IO
Imports System.Linq
Imports System.Text

Namespace E2
    Public Class Data
        Public Property Varenummer As Integer
        Public Property Varegruppenavn As String
        Public Property Varenavn As String
        Public Property Pris As Double
        Public Property Lagerstatus As String
        Public Property Vaegt As Double
        Public Property Modelbetegnelse As String
    End Class
    Public Class CSVReader
        Private stream As StreamReader
        Private fieldsep As Char
        Private strquote As Char
        Public Sub New(stream As StreamReader, fieldsep As Char, strquote As Char)
            Me.stream = stream
            Me.fieldsep = fieldsep
            Me.strquote = strquote
        End Sub
        Public Function ReadLine() As List(Of String)
            Dim line As String = stream.ReadLine()
            If line Is Nothing Then
                Return Nothing
            End If
            Dim res As New List(Of String)()
            Dim inq As Boolean = False
            Dim tmp As New StringBuilder("")
            For Each c As Char In line
                If c = fieldsep AndAlso Not inq Then
                    res.Add(tmp.ToString())
                    tmp = New StringBuilder("")
                ElseIf c = strquote Then
                    inq = Not inq
                Else
                    tmp.Append(c)
                End If
            Next
            res.Add(tmp.ToString())
            Return res
        End Function
        Public Function ReadLine(Of T As {Class, New})(ParamArray asgn As Action(Of String, T)()) As T
            Dim raw As List(Of String) = ReadLine()
            If raw Is Nothing Then
                Return Nothing
            End If
            Dim o As New T()
            For i As Integer = 0 To asgn.Length - 1
                asgn(i)(raw(i), o)
            Next
            Return o
        End Function
        Public Function ReadAllLines(Of T As {Class, New})(ParamArray asgn As Action(Of String, T)()) As List(Of T)
            Dim res As New List(Of T)()
            Dim o As T = ReadLine(asgn)
            While o IsNot Nothing
                res.Add(o)
                o = ReadLine(asgn)
            End While
            Return res
        End Function
        Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
            target = value
            Return value
        End Function
    End Class
    Public Class Program
        Public Shared Sub Main(args As String())
            Using sr As New StreamReader("h:\work\mydata.csv")
                Dim csv As New CSVReader(sr, ","c, """"c)
                Dim data As List(Of Data) = csv.ReadAllLines(Of Data)(
Sub(s, o)
    o.Varenummer = Integer.Parse(s)
End Sub,
Sub(s, o)
    o.Varenavn = s
End Sub)
                ' find the text for id 2
                ' Console.WriteLine(Double.Parse(data.Find(Function(r) r.Varenummer = 11426).Varenavn))
                ' find all id's where text contains a 'm' or 'M'
                For Each o As Data In data.Where(Function(r) r.Varenavn.ToLower().Contains("m"c))
                    Console.WriteLine(o.Varenummer & " " & o.Varenavn & " " & o.Pris)
                Next
            End Using
            Console.ReadKey()
            Console.ReadLine()
        End Sub
    End Class
End Namespace

den brokker sig når jeg prøver at køre med flere vare. og jeg kan ikke få pris med

Den brokker sig her
o.Varenummer = Integer.Parse(s)  'Inputstrengen var ikke i et korrekt format.
jeg har prøver at lave den om til string men det virker heller ikke

jeg ved ikke om det betyder nåde men første line er table info

Varenummer,Varegruppenavn,Varenavn,Pris,Lagerstatus[JaLagerEllerLeveringstidenForVaren],Vaegt,Modelbetegnelse

ps jeg er glad for du gider hjælpe det er jeg meget glad for. :)
Avatar billede arne_v Ekspert
04. juli 2016 - 19:08 #13
Ah - den linie skal skippes saa.

            Using sr As New StreamReader("h:\work\mydata.csv")
                Dim csv As New CSVReader(sr, ","c, """"c)

->
            Using sr As New StreamReader("h:\work\mydata.csv")
                sr.ReadLine() ' skip line with headers
                Dim csv As New CSVReader(sr, ","c, """"c)
Avatar billede SommerFyr Seniormester
04. juli 2016 - 19:35 #14
Fedt..
Den brokker sig her
o.Varenummer = Integer.Parse(s)  'Inputstrengen var ikke i et korrekt format.
jeg har prøver at lave den om til string men det virker heller ikke

jeg ved ikke om det betyder nåde men første line er table info

Varenummer,Varegruppenavn,Varenavn,Pris,Lagerstatus[JaLagerEllerLeveringstidenForVaren],Vaegt,Modelbetegnelse
Avatar billede arne_v Ekspert
04. juli 2016 - 20:33 #15
Skipper du den linie nu?
Avatar billede SommerFyr Seniormester
04. juli 2016 - 22:04 #16
Ja det tro jeg. er ikke sikker på hvordan jeg skal teste det eller lave et loop så jeg kan se alle
Avatar billede arne_v Ekspert
04. juli 2016 - 23:12 #17
Eksempel paa dump loop (samme eksempel):

                For Each o As Data In data
                    Console.WriteLine("{0},""{1}""", o.Id, o.Text)
                Next
Avatar billede SommerFyr Seniormester
04. juli 2016 - 23:51 #18
Når jeg gør det så brokker den sig her

Sub(s, o)
    o.Id = Integer.Parse(s)  <-
End Sub,
Avatar billede arne_v Ekspert
05. juli 2016 - 00:47 #19
Kan du uddybe "brokker sig"?
Avatar billede SommerFyr Seniormester
05. juli 2016 - 01:12 #20
Sub(s, o)
    o.Varenummer = Integer.Parse(s)  <-- Fejl  Inputstrengen var ikke i et korrekt format.
End Sub,


Jeg har prøver at rette
Public Property Varenummer As Integer til string i min data class men det virker heller ikke.
Avatar billede arne_v Ekspert
05. juli 2016 - 01:25 #21
Hvis du aendrer den til string saa skal du ikke bruge Integer.Parse
Avatar billede arne_v Ekspert
05. juli 2016 - 01:27 #22
NB: Jeg kan se at du har 7 properties men kun 2 sub's - det er nok ikke optimalt.

Logikken er:
- foerste sub processer foerste felt
- anden sub processed andet felt
...
- syvende sub processer syvende felt
Avatar billede SommerFyr Seniormester
05. juli 2016 - 01:41 #23
Og det betyder ?
Avatar billede arne_v Ekspert
05. juli 2016 - 02:17 #24
Hvis du kun giver 2 ud af 7 properties vaerdier, saa mangler du jo noget ...
Avatar billede SommerFyr Seniormester
05. juli 2016 - 02:39 #25
nu har jeg rette følgen

Sub(s, o)
    o.Varenummer = Integer.Parse(s)
End Sub,
Sub(s, o)
    o.Varegruppenavn = s
End Sub,
Sub(s, o)
    o.Varenavn = s
End Sub,
Sub(s, o)
    o.Pris = s
End Sub,
Sub(s, o)
    o.Lagerstatus = s
End Sub,
Sub(s, o)
    o.Modelbetegnelse = s
End Sub)


Men nu giver den fejl her
        Public Function ReadLine(Of T As {Class, New})(ParamArray asgn As Action(Of String, T)()) As T
            Dim raw As List(Of String) = ReadLine()
            If raw Is Nothing Then
                Return Nothing
            End If
            Dim o As New T()
            For i As Integer = 0 To asgn.Length - 1
                asgn(i)(raw(i), o)  <--  Indekset lå uden for området. Det må ikke være negativt og skal være mindre end størrelsen på samlingen.
Parameternavn: index
            Next
            Return o
        End Function
Avatar billede arne_v Ekspert
05. juli 2016 - 02:49 #26
Hvor mange felter er der i filen?
Avatar billede SommerFyr Seniormester
05. juli 2016 - 10:18 #27
Hej Arne

der er følgen felter
Varenummer,Varegruppenavn,Varenavn,Pris,Lagerstatus[JaLagerEllerLeveringstidenForVaren],Vaegt,Modelbetegnelse

som jeg har prøvet at sætte ind i data
Public Class Data
        Public Property Varenummer As Integer
        Public Property Varegruppenavn As String
        Public Property Varenavn As String
        Public Property Pris As Double
        Public Property Lagerstatus As String
        Public Property Vaegt As Double
        Public Property Modelbetegnelse As String
    End Class

er det korrekt ?
Avatar billede arne_v Ekspert
05. juli 2016 - 16:20 #28
7 felter i fil. 7 properties i klasse.

Hvis der er 7 subs, saa burde det passe.

Hvis altsa typen passer.

String skal  bare have:
= s

Integer skal have:
= Integer.Parse(s)

Double skal have:
= Double.Parse(s)

Decimal skal have:
= Decimal.Parse(s)

PS: Brug Decimal ikke Double til penge.
Avatar billede SommerFyr Seniormester
05. juli 2016 - 16:48 #29
Opdage jeg kun have 6 så fik lige oprette den siste så vi kom op på 7..
men den bliver ved med at brokke sig

Public Function ReadLine(Of T As {Class, New})(ParamArray asgn As Action(Of String, T)()) As T
            Dim raw As List(Of String) = ReadLine()
            If raw Is Nothing Then
                Return Nothing
            End If
            Dim o As New T()
            For i As Integer = 0 To asgn.Length - 1
                asgn(i)(raw(i), o)    <-- Indekset lå uden for området. Det må ikke være negativt og skal være mindre end størrelsen på samlingen.
Parameternavn: index
            Next
            Return o
        End Function
Avatar billede arne_v Ekspert
05. juli 2016 - 16:53 #30
proev og udskriv indholdet af raw og se om der er noget der falde i oejnene
Avatar billede arne_v Ekspert
05. juli 2016 - 16:54 #31
bruger du , og " i CSV formatet?
Avatar billede SommerFyr Seniormester
05. juli 2016 - 16:56 #32
Jeg har prøve med en minder fil og det virker. dog et par fejl med pris
men den kan smide alt data ud som den skal så måske er det den meget stor csv fil der er problem.
Avatar billede arne_v Ekspert
05. juli 2016 - 17:08 #33
Det burde virke med en 30 MB fil.

Men jeg tror maaske at min CSV parser er for simpel.

Maaske ryger den af sporet fordi der er " i en tekst streng.

Hvordan haandterer dit CSV format det? Dublering aka "a""b" eller escape "a\"b"?
Avatar billede SommerFyr Seniormester
05. juli 2016 - 17:13 #34
Et lille del af fil så du kan se
Varenummer,Varegruppenavn,Varenavn,Pris,Lagerstatus[JaLagerEllerLeveringstidenForVaren],Vaegt,Modelbetegnelse
102052,"AMD processorer","AMD A serie A4-6320 3.8GHz Dual-Core  FM2",329,JA,0.265,AD6320OKHLBOX
1011403,"AMD processorer","AMD A serie A4-5300 3.4GHz Dual-Core  FM2",299,JA,0.266666,AD5300OKHJBOX
1011404,"AMD processorer","AMD A serie A6-5400K 3.6GHz Dual-Core  FM2 ",435.11,NEJ,0.263333,AD540KOKHJBOX
1011410,"AMD processorer","AMD A serie A4-3300 2.5GHz Dual-Core  FM1 ",84.93,NEJ,0,AD3300OJZ22HX
Avatar billede arne_v Ekspert
05. juli 2016 - 17:24 #35
Det viser desvaerre ikke et tilfaelde med quote i quote
Avatar billede SommerFyr Seniormester
05. juli 2016 - 17:30 #36
Jeg er lidt usikker på hvordan jeg kan se det for der er desværre ingen hjælp fra firma enu.
Avatar billede arne_v Ekspert
05. juli 2016 - 21:02 #37
Prov og find ud af hvad den linie som giver problemer indeholder.
Avatar billede arne_v Ekspert
05. juli 2016 - 21:03 #38
Public Function ReadLine() As List(Of String)
            Dim line As String = stream.ReadLine()
            If line Is Nothing Then
                Return Nothing
            End If

->

      Public Function ReadLine() As List(Of String)
            Dim line As String = stream.ReadLine()
            If line Is Nothing Then
                Return Nothing
            End If
            Console.WriteLine(line)

og se hvad den sidste linie udskrevet inden fejl er.

(husk at slette den igen senere fordi der vil komme rigtigt mange linier ud)
Avatar billede SommerFyr Seniormester
05. juli 2016 - 21:53 #39
er lidt usikker på hvor det er jeg skal rette fordi min ser ikke helt sådan ud.

        Public Function ReadLine(Of T As {Class, New})(ParamArray asgn As Action(Of String, T)()) As T
            Dim raw As List(Of String) = ReadLine()
            If raw Is Nothing Then
                Return Nothing
            End If

            Dim o As New T()
            For i As Integer = 0 To asgn.Length - 1
                asgn(i)(raw(i), o)
            Next
            Return o
        End Function
Avatar billede SommerFyr Seniormester
05. juli 2016 - 21:54 #40
fandt den..
Avatar billede SommerFyr Seniormester
05. juli 2016 - 22:11 #41
Jubii der kom vi et godt stykke gemmen..

Det ser ud til at der er en fejl i deres data..

da jeg kom til en line som ikke har de antal poster den skal have.

Indekset lå uden for området. Det må ikke være negativt og skal være mindre end størrelsen på samlingen.
Parameternavn: index

Så jeg må nok skrive til dem.
Avatar billede SommerFyr Seniormester
05. juli 2016 - 22:20 #42
Gør det nåde at der bliver brugt " i text sådan at en text kommer til at se sådan ud LCD PANEL-15.4"  ?
Avatar billede arne_v Ekspert
06. juli 2016 - 01:42 #43
Ja. Det er hvad jeg spurgte om i #33
Avatar billede arne_v Ekspert
06. juli 2016 - 03:02 #44
Her er en ny version som er bedre til at haandtere " i vaerdier.


    Public Class CSVReader
        Private stream As StreamReader
        Private fieldsep As Char
        Private strquote As Char
        Private esc As Char
        Public Sub New(stream As StreamReader, fieldsep As Char, strquote As Char, Optional esc As Char = ControlChars.NullChar)
            Me.stream = stream
            Me.fieldsep = fieldsep
            Me.strquote = strquote
            Me.esc = esc
        End Sub
        Public Function ReadLine() As List(Of String)
            Dim line As String = stream.ReadLine()
            If line Is Nothing Then
                Return Nothing
            End If
            Dim res As New List(Of String)()
            Dim inq As Boolean = False
            Dim skip As Boolean = False
            Dim tmp As New StringBuilder("")
            For i As Integer = 0 To line.Length - 1
                Dim c As Char = line(i)
                If skip Then
                    tmp.Append(c)
                    skip = False
                ElseIf (c = fieldsep) AndAlso Not inq Then
                    res.Add(tmp.ToString())
                    tmp = New StringBuilder("")
                ElseIf (c = esc) AndAlso (i < line.Length - 1) AndAlso (line(i + 1) = strquote) Then
                    skip = True
                ElseIf (c = strquote) AndAlso ((tmp.Length = 0) OrElse inq) Then
                    inq = Not inq
                Else
                    tmp.Append(c)
                End If
            Next
            res.Add(tmp.ToString())
            Return res
        End Function
        Public Function ReadLine(Of T As {Class, New})(ParamArray asgn As Action(Of String, T)()) As T
            Dim raw As List(Of String) = ReadLine()
            If raw Is Nothing Then
                Return Nothing
            End If
            Dim o As New T()
            For i As Integer = 0 To asgn.Length - 1
                asgn(i)(raw(i), o)
            Next
            Return o
        End Function
        Public Function ReadAllLines(Of T As {Class, New})(ParamArray asgn As Action(Of String, T)()) As List(Of T)
            Dim res As New List(Of T)()
            Dim o As T = ReadLine(asgn)
            While o IsNot Nothing
                res.Add(o)
                o = ReadLine(asgn)
            End While
            Return res
        End Function
        Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
            target = value
            Return value
        End Function
    End Class


og:

Dim csv As New CSVReader(sr, ","C, """"C, """"C)
Avatar billede SommerFyr Seniormester
14. august 2016 - 17:01 #45
Hej  arne_v

Jeg vil bare lige sige jeg ikke har glemt dig men venter på at min udbyder vender tilbage fra sommerferie. samt at de får rette fejl på data..
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester