csv-datei in ein array importieren

Anfängerfragen zum Programmieren mit PureBasic.
psxx66
Beiträge: 5
Registriert: 22.07.2012 19:09

csv-datei in ein array importieren

Beitrag von psxx66 »

Hallo zusammen,

in der Regel arbeite ich mit/in Excel und kenne mich da auch ganz gut aus.
Bei einer aktuellen Aufgabe komme ich da jedoch an Geschwindigkeitsgrenzen und möchte meine Berechnungen in PureBasic durchführen.

Dazu müsste ich eine csv-Datei in ein Array einlesen, dort einen Schwung einfacher Berechnungen durchführen und dann das Array wieder als csv-Datei schreiben.
Meine csv-Datei beinhalten Aktienkursdaten und sieht immer so aus:

Date;Open;Close;High;Low
03.10.2011;99,595;99,595;99,595;99,595
04.10.2011;98,155;98,155;98,155;98,155
05.10.2011;98,807;98,807;98,807;98,807
06.10.2011;99,925;99,925;99,925;99,925
07.10.2011;101,339;101,339;101,339;101,339
08.10.2011;101,339;101,339;101,339;101,339
09.10.2011;101,339;101,339;101,339;101,339
10.10.2011;102,41;102,41;102,41;102,41

Meine Versuche, Code aus dem Forum zu übernehmen sind jedes mal gescheitert :-(
Habt Ihr eine Hilfestellung für mich, wie ich meine Datei erstmal in ein Array bekomme ... das wäre toll.
Vielen Dank für Eure Ideen und Hilfe

Gruß
Peter
Benutzeravatar
mk-soft
Beiträge: 3700
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: csv-datei in ein array importieren

Beitrag von mk-soft »

Habe zu viel zeit ;)

P.S. Siehe auch SplitString.pbi

Code: Alles auswählen

;-TOP 
; Read And Write TextFile by mk-soft, v1.02, 28.03.2020

EnableExplicit

Procedure ReadFileToList(FileName.s, List TextList.s()) ; Result Format (BOM)
  Protected file, format
  
  ClearList(TextList())
  
  file = ReadFile(#PB_Any, FileName)
  If file = 0
    Debug "Error Open File: " + FileName
    ProcedureReturn 0
  EndIf
  
  format = ReadStringFormat(file)
  If format = 0
    Debug "Error Read BOM: " + FileName
    CloseFile(file)
    ProcedureReturn 0
  EndIf
  
  While Not Eof(file)
    AddElement(TextList())
    TextList() = ReadString(file, format)
  Wend
  
  CloseFile(file)
  
  ProcedureReturn format
  
EndProcedure

; ----

Procedure WriteFileFromList(FileName.s, List TextList.s(), Format = #PB_UTF8) ; Result wrote lines
  Protected file, cnt
  
  If Format <> #PB_Ascii And Format <> #PB_UTF8 And Format <> #PB_Unicode
    Debug "Error BOM not supported: " + FileName
    ProcedureReturn 0
  EndIf
  
  file = CreateFile(#PB_Any, FileName, Format)
  If file = 0
    Debug "Error Create File: " + FileName
    ProcedureReturn 0
  EndIf
  
  If WriteStringFormat(file, Format) = 0
    Debug "Error Write BOM: " + FileName
    CloseFile(file)
    ProcedureReturn 0
  EndIf
    
  ForEach TextList()
    If WriteStringN(file, TextList()) = 0
      Debug "Error Write Line: " + FileName
      CloseFile(file)
      ProcedureReturn 0
    Else
      cnt + 1
    EndIf
  Next
  
  CloseFile(file)
  
  ProcedureReturn cnt
  
EndProcedure

; ****

Procedure SplitStringArray(String.s, Separator.s, Array Result.s(1), DQuote = #False)
  Protected *String.character, *Separator.character
  Protected *Start, *End, exit, lock, do, dq, len , count, size
  
  size = 7
  Dim Result(size)
  *String = @String
  *Separator = @Separator
  *Start = *String
  *End = *String
  If DQuote
    Repeat
      If *String\c = 0
        exit = #True
        do = #True
        If Not dq
          *End = *String
        EndIf
      Else
        If *String\c = '"'
          If Not lock
            lock = #True
            dq = #True
            *Start = *String + SizeOf(character)
          Else
            lock = #False
            *End = *String
          EndIf
        EndIf
        If *String\c = *Separator\c And Not lock
          do = #True
          If Not dq
            *End = *String
          EndIf
        EndIf
      EndIf
      If do
        If size < count
          size + 8
          ReDim Result(size)
        EndIf
        len = (*End - *Start) / SizeOf(character)
        If Len > 0
          Result(count) = PeekS(*Start, len) 
        EndIf
        *Start = *String + SizeOf(character)
        count + 1
        do = #False
        dq = #False
      EndIf
      *String + SizeOf(character)
    Until exit
  Else
    Repeat
      If *String\c = 0
        exit = #True
        do = #True
        *End = *String
      Else
        If *String\c = *Separator\c
          do = #True
          *End = *String
        EndIf
      EndIf
      If do
        If size < count
          size + 8
          ReDim Result(size)
        EndIf
        len = (*End - *Start) / SizeOf(character)
        If Len > 0
          Result(count) = PeekS(*Start, len) 
        EndIf
        *Start = *String + SizeOf(character)
        count + 1
        do = #False
      EndIf
      *String + SizeOf(character)
    Until exit
  EndIf
  ReDim Result(count - 1)
  ProcedureReturn count
EndProcedure

; ----

; *********

Structure udtData
  Array Fields.s(0)
  Date.s
  Open.d
  Close.d
  High.d
  Low.d
  ;TODO
  ;Add result variables
EndStructure

Global NewList Text.s()
Global NewList MyData.udtData()

Define filename.s, bom, cnt, Fields.s

; Read CSV to text list
filename.s = OpenFileRequester("Open", "", "", 0)
If filename
  bom = ReadFileToList(filename, Text())
  Debug "BOM = " + bom
EndIf

; Save and remove first line
FirstElement(Text())
Fields = Text() 
DeleteElement(Text())

; Split and convert data
ForEach Text()
  AddElement(MyData())
  SplitStringArray(Text(), ";", MyData()\Fields(), #False)
  With MyData()
    \Date = \Fields(0)
    \Open = ValD(ReplaceString(\Fields(1), ",", "."))
    \Close = ValD(ReplaceString(\Fields(2), ",", "."))
    \High = ValD(ReplaceString(\Fields(3), ",", "."))
    \Low = ValD(ReplaceString(\Fields(4), ",", "."))
    ;TODO
    
  EndWith
  Debug Text()
Next

ShowVariableViewer()
CallDebugger

;TODO
End

filename.s = SaveFileRequester("Save", filename + ".csv", "", 0)
If filename
  cnt = WriteFileFromList(filename, Text(), bom)
EndIf

Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
hjbremer
Beiträge: 822
Registriert: 27.02.2006 22:30
Computerausstattung: von gestern
Wohnort: Neumünster

Re: csv-datei in ein array importieren

Beitrag von hjbremer »

etwas einfacher als Hinweis auf eine von vielen Möglichkeiten

Code: Alles auswählen

#dnr = 0
#filename = "Test.txt"

Procedure.i CountLines(file$)
   Protected anzahl
   
   If ReadFile(#dnr, file$)        ; wenn die Datei geöffnet werden konnte, setzen wir fort...
      While Eof(#dnr) = 0          ; sich wiederholende Schleife bis das Ende der Datei ("end of file") erreicht ist
         Debug ReadString(#dnr)    ; Zeile für Zeile im Debugger-Fenster anzeigen
         anzahl + 1
      Wend
      CloseFile(#dnr)               ; schließen der zuvor geöffneten Datei
   Else
      MessageRequester("Information","Konnte Datei nicht öffnen!")
   EndIf
   
   ProcedureReturn anzahl
EndProcedure

Procedure.i ReadLines(file$, lines, Array text$(1))
   Protected j
   
   ReadFile(#dnr, file$)
      For j = 1 To lines         
         text$(j) = ReadString(#dnr)
      Next
      CloseFile(#dnr)
   
EndProcedure

;MainProgramm

Define j, k, lines
Define datum$, text$
Define wert1_1$, wert1_2$ 
;usw
       
Define Dim daten$(0)

lines = CountLines(#filename) : Debug "Zeilen: " + lines : Debug ""

If lines
   
   ReDim daten$(lines)
   
   ReadLines(#filename, lines, daten$())
   
   For j = 1 To lines
      Debug daten$(j)
      
      datum$ = StringField(daten$(j), 1, ";") : Debug datum$
      
      text$  = StringField(daten$(j), 2, ";") : Debug text$
      wert1_1$ = StringField(text$, 1, ",") : Debug wert1_1$ 
      wert1_2$ = StringField(text$, 2, ",") : Debug wert1_2$  
      ;usw
      Debug "-----"
      
   Next
   
EndIf

   
   
Purebasic 5.70 x86 5.72 X 64 - Windows 10

Der Computer hat dem menschlichen Gehirn gegenüber nur einen Vorteil: Er wird benutzt
grüße hjbremer
Benutzeravatar
Pelagio
Beiträge: 424
Registriert: 11.11.2004 17:52
Computerausstattung: Intel Core i3-4170 CPU 3,70 GHz
8,00 GB Arbeitsspeicher
WIN 10 Pro 64 Bit Betriebssystem
Wohnort: Bremen

Re: csv-datei in ein array importieren

Beitrag von Pelagio »

Hallo Leute Ihr seid schnell und es gibt viele Wege nach Rom, so auch hier gibt es einige Ansätze das 'Problem' zu lösen.
Da ich jetzt schon mal soweit war, wollt ich meinen Ansatz nicht in die Tonne treten.

Code: Alles auswählen

EnableExplicit

#idFile = 0

Structure strucData
	sDate.s[10]
	sOpen.f
	sClose.f
	sHight.f
	sLow.f
EndStructure

Define NewList gData.strucData()
Define.s gValue

If ReadFile(#idFile, "Test.csv")
	gValue = ReadString(#idFile)
	While (Eof(#idFile)=#False)
		gValue = ReadString(#idFile)
		gValue = ReplaceString(gValue, Chr(44), Chr(46))
		AddElement(gData())
		With gData()
			\sDate  =         StringField(gValue,1, Chr(59))
			\sOpen = ValF(StringField(gValue,2, Chr(59)))
			\sClose = ValF(StringField(gValue,3, Chr(59)))
			\sHight = ValF(StringField(gValue,4, Chr(59)))
			\sLow   = ValF(StringField(gValue,5, Chr(59)))
		EndWith
	Wend
	CloseFile(#idFile)
Else
	MessageRequester("Information","Konnte Datei nicht öffnen!")
EndIf

ForEach gData()
	With gData()
		Debug \sDate + " | " + 
			StrF(\sOpen , 3) + " | " + 
			StrF(\sClose, 3) + " | " + 
			StrF(\sHight, 3) + " | " + 
			StrF(\sLow  , 3)
	EndWith
Next
Ohne Zeit kein Fleiß
Auf neustem Stand zu sein ist eine Kunst die nicht jeder perfektioniert [Win10Pro(64); PB6.10 LTS]. :allright:
Benutzeravatar
mk-soft
Beiträge: 3700
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: csv-datei in ein array importieren

Beitrag von mk-soft »

Haben wohl viele zu viel zeit ;)

Daran denken CSV Dateien auch DQUOTE ["] enthalten können.
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
psxx66
Beiträge: 5
Registriert: 22.07.2012 19:09

Re: csv-datei in ein array importieren

Beitrag von psxx66 »

Hallo an alle mit zu viel Zeit :-)

Vielen Dank für Eure Ideen.
Ich teste sie aus und gebe Euch dann ein Feedback.

Super, dass Ihr mir so schnell geholfen habt.

Gruß
Peter
Antworten