Entwickler-Ecke
Delphi Language (Object-Pascal) / CLX - csv - Strings parsen
Martello - Fr 11.06.10 23:25
Titel: csv - Strings parsen
Eine einfache Frage - nur nicht für mich: :?
Wie kann ich in Delphi elegant mit readln(text, ..,..,...,.) kommaseparierte Substrings beim Einlesen "erfassen" und die Elemente anschließend typkonvertieren und in ein entsprechendes Record einfügen? Die Substrings können von Zeile zu Zeile in ihrer Länge variieren.
Danke für Hilfe,
M.
Xentar - Fr 11.06.10 23:55
Wenn die wirklich getrennt sind, könntest du TStringList.DelimitedText bzw. TStringList.Commatext verwenden
jaenicke - Fr 11.06.10 23:56
Und effizient würde ich das ganze zeichenweise durchgehen und jeweils in den entsprechenden Teil des Records kopieren.
Wenn man das mit PChar macht, geht das seht schnell.
Martello - Sa 12.06.10 13:00
Xentar hat folgendes geschrieben : |
| Wenn die wirklich getrennt sind, könntest du TStringList.DelimitedText bzw. TStringList.Commatext verwenden |
Wirklich getrennt werden die durch Kommata; am Anfang sogar noch mit Excel erzeugt und gespeichert via *.csv :oops:
Mit TStringList habe ich bereits ein wenig Erfahrung; allerdings hatte ich es seiner Zeit nur verwendet, um eine erzeugte
Matrix zu buffern, um sie schließlich als *.txt exportieren zu können. Explizit habe ich also "Delimiter" noch nicht angewendet.
Mit TStingList lese ich doch die ganze Datei auf einmal; und anschließend würde ich Zeile für Zeile separieren. Irgendwie so ähnlich - dachte ich - müsste es wohl gehen. :? Und da die Substringlänge einer Spalte manchmal von Zeile zu Zeile variiert, dürfte das mit TStringList.Delimited.Text bzw. ..Commatext wohl die einfachere Methode sein im Vergleich zu jaenickes Emfehlung pro PChar. (Es sei denn, man hat bereits viel Routine im Umgang mit Pointern :wink: )
Ich bin gespannt, danke für die Tipps.
M.
jaenicke - Sa 12.06.10 15:06
Wenn die aus Excel kommen, würde ich eher dazu raten die Datei auch als Exceldatei zu speichern. Denn dann muss man nicht erst lange parsen.
Was die Pointer angeht:
So schwer und viel Quelltext ist das nicht. Siehe hier, da lese ich zeichenweise aus einem Speicherbereich:
http://www.delphi-forum.de/viewtopic.php?t=99933
Das grundsätzliche Vorgehen ist, dass man einen PChar auf das erste Zeichen des Strings hat. Dann inkrementiert man diesen Pointer jeweils und hat dann (da ein Pointer nullterminiert ist) immer den Rest des Strings drin. Aber das alles ohne den String an sich ändern zu müssen.
Dadurch geht das ganze sehr viel schneller. Ich suche das Endzeichen und kopiere dann die Zeichen zwischen dem aktuellen Anfang und dem Zeichen in den Record. Dann setze ich den Anfang auf das folgende Zeichen. Und so weiter. ;-)
Die Frage ist auch wie schnell das sein muss usw., denn Optimierung ist zwar schön (und macht mir auch Spaß), aber man muss eben immer Lesbarkeit und Wartbarkeit des Codes gegen die an der Stelle wirklich notwendige Geschwindigkeit abwägen.
Martello - Sa 12.06.10 18:38
jaenicke hat folgendes geschrieben : |
| Wenn die aus Excel kommen, würde ich eher dazu raten die Datei auch als Exceldatei zu speichern. Denn dann muss man nicht erst lange parsen. |
Ich möchte mich nicht auf das *.xls-Format festlegen; später soll es kommaseparierter *.txt sein, egal wie die Endungen dann lauten. Das mit PChar muss auch noch warten. Erst mal hab ich den Umgang mit TStringList zu üben: :oops:
Delphi-Quelltext
1: 2: 3:
| var sl, slRow : TStringList; line, col : integer; |
Aus dem vorstehenden Delphi-Text lerne ich, dass man auch einzelne Strings/Zeilen ("slRow") als TSringList verwenden kann/sollte, um zu...
Delphi-Quelltext
1: 2: 3:
| slRow.DelimitedText := sl[line]; StringGrid1.Rows[line].Assign(slRow); |
Diese Zeilen habe ich aus einem Beispiel, das in ein StringGrid einliest. Das geht mit ...Assign(slRow) ja sehr elegant.
Um meine Substrings in ein Record "einzusokonvertieren" werde ich also auch so etwas wie
slRow.DelimitedText := sl[line] verwenden. Wie picke ich aber danach am einfachsten alle einzelnen Elemente aus meiner Zeile heraus? Gibt es hierfür Indizes oder Items oder ähnliches?
M.
jaenicke - Sa 12.06.10 19:33
Martello hat folgendes geschrieben : |
| Wie picke ich aber danach am einfachsten alle einzelnen Elemente aus meiner Zeile heraus? Gibt es hierfür Indizes oder Items oder ähnliches? |
Delphi-Quelltext
1: 2: 3:
| slRow[0] slRow[1] ... |
;-)
Martello - Sa 12.06.10 20:33
jaenicke hat folgendes geschrieben : |
Delphi-Quelltext 1: 2: 3:
| slRow[0] slRow[1] ... | ;-) |
Ich hatte in der Zwischenzeit einmal in der Hilfe nachgelesen, und bin ein wenig erschrocken, dass es so einfach ist... :?
In TurboPascal verwende ich delay(ms), um Prozesse zu verlangsamen. Irgendwo las ich, in Delphi gäb's dafür sleep(ms)
(ein Tutorial über Timer in Delphi habe ich immerhin auch schon gefunden).
Aber bei "Sleep(ms)" innerhalb einer Schleife einer TForm1.Button1Click(Sender: TObject);
wacht er nicht mehr auf, da scheint irgendwas zu hängen, oder woran sonst könnte das liegen?
Gibt es einee einfachen Ersatz für mein delay() in Delphi?
M.
Martello - Di 15.06.10 23:32
jaenicke hat folgendes geschrieben : |
Aber meistens sind solche Fragen Symptome eines schlechten / nicht durchdachten Konzepts... Meistens gibt es eine deutlich bessere Lösung. |
Mit Delay() wollte ich den Prozess eigentlich nur verlangsamen, um ihm dabei zusehen zu können, wie er alle 256*256 Keys meines Array in ein Edit schreibt. Ohne Delay() sehe ich nur den letzten Wert. Und soll ich ihm jetzt trauen, dass er alle anderen zuvor auch korrekt geschrieben hat? :wink:
Aber Spaß beiseite:
Ich möchte ja 4 mal in der Sekunde GPS-Daten aus einem UBLOX via RS232 einlesen. Diese Strings kommen schön regelmäßig, und damit habe ich auch gleich einen exakten Taktgeber für mein Progrämmchen, von dem ich leider nicht weiß, ob ich es je zum Laufen kriege... :(
Insofern darf die Lektüre diverser "Timingkonzepte in Delphi" ruhig noch ein wenig liegen bleiben. Ich habe Cport erfolgreich installiert; nun studiere ich erst mal die mitgelieferte Hilfe. Weißt Du rein zufällig von ein paar passenden Delphi-Zeilen, die an einem Comport lauschen und regelmäßig Stringsendungen unbekannter Länge (die Längen der $GPRMC-Strings variieren leider) nach Delphi transportieren?
M.
Narses - Di 15.06.10 23:35
Moin!
Bitte erstelle für jede deiner Fragen ein separates Topic, da die Diskussion mehrerer Fragen in einem Topic für gewöhnlich für Verwirrung und Durcheinander sorgt. Danke. ;)
cu
Narses
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!