Seite 1 von 1
CSV Reader
Verfasst: 30.03.2013 15:06
von KeyKon
Hat zufällig einer eine Prozedur die eine CSV in eine Strukturierte Liste/Array einließt und will sie hier veröffentlichen, war mal wieder nicht in der Lage mit der SuFu was zu finden.
Dachte eigentlich das ist ja schnell gemacht nur muss sie auch mit Feldern in denen Zeilenumbrüche oder Kommas vorkommen (Die sind dann durch Anführungszeichen eingeschlossen) zurechtkommen, da ist mir spontan keine performante Möglichkeit eingefallen...
Achja bitte steinigt mich nicht wenn sowas in 10 Zeilen zu lösen ist, weiht mich in dem Fall einfach ein
LG KeyKon
Re: CSV Reader
Verfasst: 30.03.2013 19:21
von #Ton
Code: Alles auswählen
EnableExplicit
Structure struc_INPUT
val1.l
val2.l
val3.l
EndStructure
Procedure ReadCSVFile(Array a.struc_INPUT(1), CSV_Path.s)
Protected.l z = #Null
Protected.s SepChar = ";"
Protected.s String = ""
Protected.s StringNeeded = ""
;> (CSV-)Datei einlesen
If ReadFile(0, CSV_Path) = #Null
MessageRequester("Error", "Couldn't read file:" + Chr(13) + CSV_Path)
End
EndIf
;> Array-Feldgröße anpassen
While Eof(0) = #Null
ReadString(0)
z+1
Wend
ReDim a(z-1)
z = 0
FileSeek(0,0)
;> Array füllen
While Eof(0) = #Null
String = ReadString(0, ReadStringFormat(0))
StringNeeded = Left ( String, FindString(String, SepChar,0)-1 )
String = Right( String, Len(String)-FindString(String, SepChar, 0) )
a(z)\val1 = Val ( StringNeeded )
StringNeeded = Left ( String, FindString(String, SepChar,0)-1 )
String = Right( String, Len(String)-FindString(String, SepChar, 0) )
a(z)\val2 = Val ( StringNeeded )
a(z)\val3 = Val(String)
z+1
Wend
CloseFile(0)
EndProcedure
Global Dim csv.struc_INPUT(#Null)
ReadCSVFile(csv(), GetHomeDirectory()+"Desktop\test.csv")
Zugehöriger CSV-Dateiinhalt zum testen:
648;98;138
3186;3971;398
18638;34834;34384
Re: CSV Reader
Verfasst: 30.03.2013 20:30
von NicTheQuick
Damit kann man aber keine Strings einlesen und schon gar nicht Strings, die in Anführungszeichen stehen und sich über mehrere Zeilen erstrecken, z.B. das hier:
Vorname,Nachname,PLZ,Adresse, Telefon
Max,Mustermann,53118,"Musterweg 18
Musterhause", "01234/56789"
Re: CSV Reader
Verfasst: 30.03.2013 21:53
von KeyKon
Genau, für einfache Zahlenwerte/Strings hatte ich es auch schon und war ganz Happy, bis ich gemerkt hab das da unter Umständen auch Kommas und Zeilenumbrüche dabei sind (Nur bei diesen ist dann auch ein Anführungszeichen)
Trotzdem danke für die Mühe! Da sich auf die schnelle keiner gemeldet hat werd ich mich selbst an die Umsetzung machen.
Wollte ja nur mal abchecken ob das vll schon jemand in der Schublade hat, man muss sich ja keine unnötige Arbeit machen^^
LG KeyKon
Re: CSV Reader
Verfasst: 31.03.2013 08:17
von Danilo
Hier ein Character-Scanner dafür:
Code: Alles auswählen
EnableExplicit
Structure CSVEntry
List Item.s()
EndStructure
#CSV_WithDoubleQuotes = 0 ; add double quotes to the output string (default)
#CSV_WithoutDoubleQuotes = 1 ; remove double quotes from the output string
Procedure ReadCSV(*p.Character, separator.c, List lst.CSVEntry(), flags = #CSV_WithDoubleQuotes)
Protected item.s
ClearList( lst() )
If *p = 0 Or *p\c = 0
ProcedureReturn ; empty string
EndIf
AddElement(lst())
While *p\c <> 0
While *p\c <> 0
If *p\c = 34 ; DoubleQuote start
If flags = #CSV_WithDoubleQuotes
item + Chr(*p\c) ; add starting DoubleQuote
EndIf
*p + SizeOf(Character)
While *p\c <> 0 And *p\c <> 34 ; scan for DoubleQuote end
If *p\c <> 10 And *p\c <> 13 ; do not add cariage return and line feed while in string
item + Chr(*p\c)
EndIf
*p + SizeOf(Character)
Wend
If *p\c = 34
If flags = #CSV_WithDoubleQuotes
item + Chr(*p\c) ; add ending DoubleQuote
EndIf
*p + SizeOf(Character)
EndIf
Continue ; continue scanning
ElseIf *p\c = separator ; separator found. exit inner loop
*p + SizeOf(Character)
Break
ElseIf *p\c = 10 Or *p\c = 13 ; cariage return or line feed found outside string: Break
Break
Else ; other character found, so add it to current item
item + Chr(*p\c)
*p + SizeOf(Character)
EndIf
Wend
AddElement(lst()\Item()) ; add current item to the list items
lst()\Item() = item
item=""
If *p\c = 13 ; for #CR$, #LF$, #CRLF$, #LFCR$:
AddElement(lst()) ; end of line found, so add a new list entry
*p + SizeOf(Character)
If *p\c = 10
*p + SizeOf(Character)
EndIf
ElseIf *p\c = 10
AddElement(lst())
*p + SizeOf(Character)
If *p\c = 13
*p + SizeOf(Character)
EndIf
EndIf
Wend
FirstElement(lst())
If ListSize(lst())=1 And ListSize(lst()\Item())=0
ClearList(lst())
EndIf
EndProcedure
Procedure.i ReadCSVFile(filename.s, separator.c, List lst.CSVEntry(), flags = #CSV_WithDoubleQuotes)
Protected file, *mem, format, line.s, stringpointer.i, result.i
ClearList( lst() )
file = ReadFile(#PB_Any,filename)
If file
format = ReadStringFormat(file)
*mem = AllocateMemory((Lof(file)+10)*SizeOf(Character)) ; read file into memory, line by line
If *mem
stringpointer = *mem
While Not Eof(file)
line = ReadString(file,format)
If Eof(file) = 0
line + #LF$
EndIf
CopyMemoryString(@line,@stringpointer)
Wend
ReadCSV(*mem,separator,lst(),flags) ; call ReadCSV() on the memory
result = #True
FreeMemory(*mem)
EndIf
CloseFile(file)
EndIf
ProcedureReturn result
EndProcedure
NewList entries.CSVEntry()
Define csv.s
csv = "Vorname,Nachname,PLZ,Adresse, Telefon"+#LF$
csv + "Max,Mustermann,53118,"+#DQUOTE$+"Musterweg 18, "+#LF$
csv + "Musterhausen"+#DQUOTE$+", "+#DQUOTE$+"01234/56789"+#DQUOTE$
ReadCSV(@csv,',',entries())
ForEach entries()
ForEach entries()\Item()
Debug Trim(entries()\Item())
Next
Debug "-----"
Next
Debug "-----------------------------------"
csv = "648;98;138"+#CRLF$
csv + "3186;3971;398"+#LFCR$
csv + "18638;34834;34384"+#LF$
csv + "1920;8;1977"+#CR$
csv + "1;2;3"
ReadCSV(@csv,';',entries())
ForEach entries()
ForEach entries()\Item()
Debug Trim(entries()\Item())
Next
Debug "-----"
Next
Define url.s = "http://download.finance.yahoo.com/d/quotes.csv?s=C+GLAD+HIMX+INSP+INTU+HRB+JTX+PODD+SILU+WFC&f=snoghl1b2b3p2"
Define filename.s = GetTemporaryDirectory()+"quotes.csv"
If InitNetwork()
ReceiveHTTPFile(url,filename)
EndIf
Debug "- File ----------------------------"
If ReadCSVFile(filename,',',entries(),#CSV_WithoutDoubleQuotes)
ForEach entries()
ForEach entries()\Item()
Debug Trim(entries()\Item())
Next
Debug "-----"
Next
Else
Debug "unable to read file"
EndIf
DeleteFile(filename)
Re: CSV Reader
Verfasst: 31.03.2013 18:00
von Danilo
Habe mal noch 2 Flags hinzugefügt:
Code: Alles auswählen
#CSV_WithDoubleQuotes = 0 ; add double quotes to the output string (default)
#CSV_WithoutDoubleQuotes = 1 ; remove double quotes from the output string
So kannst Du auswählen ob die Anführungszeichen Teil des Ausgabestrings sind, oder nicht.
Re: CSV Reader
Verfasst: 01.04.2013 11:31
von Kiffi
@Danilo: Danke!
Grüße ... Kiffi