Entwickler-Ecke
Dateizugriff - Strings zwischen Simikolons lesen
ebs - So 20.03.05 18:04
Titel: Strings zwischen Simikolons lesen
Hallo,
ich bin absoluter Anfänger und habe ein Problem mit Dateien. Ich greife mit Delphi auf Textdateien zu, in denen sowohl Strings in Zeilen, als auch zwischen Simikolons stehen. Mein Problem ist, dass Delphi nun immer nur die Spalten als ein String sieht, und niemals die Simikolons. Gibt es irgendeine möglichkeit, dass Delphi auch die Strings zwischen den Simikolons erkennt, ohne dass ich die Datei neu umformatieren muss? Wenn es sein muss, kann ich auch die Simikolons in andere Zeichen ändern.
Hier ein Beispiel:
Quelltext
1: 2: 3:
| i13;15;25;58;256;128;16;32 l15;564;67;31;46;54; k88;546;54;5 |
Und der Quelltext:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure TForm1.Open1Click(Sender: TObject); var F: TextFile; S: string; begin begin if OpenDialog1.Execute then begin AssignFile(F, OpenDialog1.FileName); Reset(F); Readln(F, S); Edit1.Text := S; CloseFile(F);
end; end; end; |
Ich danke im voraus!
Moderiert von
AXMD: Code- durch Delphi-Tags ersetzt.
AXMD - So 20.03.05 18:07
:welcome:
POS und
COPY helfen da ;)
AXMD
F34r0fTh3D4rk - So 20.03.05 18:46
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| Function GetWordOfAnsiString(Text : string; WordPos : Word): string; var p : PChar; begin p := PChar(Text); repeat Dec(WordPos); while p^ <> #0 do begin if WordPos = 0 then Result := Result + p^; Inc(p); end; if WordPos = 0 then Exit; Inc(p); until p^ = #0; end; |
hilft da auch ^^
#0 lässt sich durch jedes zeichen ersetzen
wulfskin - So 20.03.05 18:53
EXPLODE
delfiphan - So 20.03.05 19:01
Die zwei Funktionen
explode und
implode müssen einfach mal gepostet werden...
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
| procedure explode(S: String; C: Char; List: TStrings); Var I, J: Integer; begin List.Clear; if S = '' then exit; J := 1; for I := 1 to length(S) do if S[I] = C then begin List.Add(Copy(S, J, I-J)); J := I+1; end; List.Add(Copy(S, J, I-J)); end;
function implode(List: TStrings; C: Char): String; Var I: Integer; begin if List.Count = 0 then begin Result := ''; exit; end else Result := List.Strings[0]; For I := 1 to List.Count-1 do Result := Result + C + List.Strings[I]; end; |
Anwendung:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| Var List : TStringList; S : String; I : Integer; begin S := 'Eintrag1;Eintrag2;Eintrag3';
List := TStringList.Create;
Explode(S,';', List); for I := 0 to List.Count-1 do S := Implode(List, ';'); List.Free; end; |
Oops, da hat einer schon nen Link gepostet. Meine Funktionen also als Alternative :)
F34r0fTh3D4rk - So 20.03.05 19:05
oder meine variante, die ich (pers) einfacher finde :roll:
delfiphan - So 20.03.05 19:08
Naja, die Prozedur ExtractStrings (unit Classes) ist mir erst heute aufgefallen, damit geht's natürlich auch.
@F34r0fTh3D4rk: Deine Prozedur macht irgendwas, auf jeden Fall nicht das gesuchte. Er/Sie will einen String, welches das Zeichen ';' enthält in mehrere Strings unterteilen.
hansa - So 20.03.05 22:21
Wo kommen denn die Semikolons überhaupt her ?
delfiphan - So 20.03.05 22:28
Dateien im CVS Format sind so. Wenn du z.B. ein Excel Sheet als CVS abspeicherst.
hansa - So 20.03.05 22:37
Das halte ich eher für ein Gerücht. 8) Zumindest im deutschsprachigen Raum verwendet man kein CSV. Wenn das dein CVS überhaupt ist. Auch nicht in Excel. Wozu so was verwenden ?
delfiphan - So 20.03.05 22:46
CSV, sorry, Tippfehler. Dass man mit Excel CSV Dateien erstellen kann ist doch kein Gerücht!? CSV ist praktisch und einfach zu implementieren. Oder erstellt deine Delphiapplikation eine xls Datei? Im Übrigen haben nicht alle Excel.
hansa - So 20.03.05 23:00
Wir reden hoffentlich von "comma separated values". Und die sind Schrott. :mrgreen: Das sollte heutzutage nicht mehr verwendet werden. Egal wie das Trennzeichen sich schimpft. Ich kann doch nicht ein Zeichen als Trennzeichen verwenden, sofern auch nur eine sehr geringe Wahrscheinlichkeit besteht, daß es innerhalb der Daten selbst verwendet wird. :shock:
delfiphan - So 20.03.05 23:05
Stimmt schon, aber für Zahlen kann man die schon gebrauchen...
hansa - Mo 21.03.05 02:42
Tja, die Links gucke ich mir erst gar nicht an. :lol: Ich lese da was von Rindvieh-Züchtung. Davon habe ich leider keine Ahnung und überlasse dieses Thema demjenigen, der weiß, wovon er spricht. 8) Ansonsten empfehle ich eben, feste Feldlängen zu verwenden. Nachzulesen im "Entwickler".
Alternative wäre natürlich auch, eine Textdatei solange umzubauen, bis sie irgendwie paßt. :P Ja, dann mal weiter so.
ebs - Mo 21.03.05 09:07
Titel: Danke!
Hallo,
ihr habt mir sehr geholfen. Eure Methoden funktionieren genauso, wie ich das haben wollte. Vielen Dank!
opfer.der.genauigkeit - Mo 21.03.05 09:25
Hi ebs,
sicherlich nicht die performanteste aber "faulste" Methode wäre das hier :lol: :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| var List: TStringList; s : string; i : integer; begin List := TStringList.Create;
s := 'test1;test2;test3;test4'; List.Delimiter := ';'; List.CommaText := s;
for i := 0 to ( List.Count - 1 ) do begin end;
List.Free; end; |
F34r0fTh3D4rk - Mo 21.03.05 11:52
@delphiphan: genau dieses "irgendwas", ist das gesuchte !
man kann damit einen string, der durch trennzeichen getrennt ist, in mehere einzelne strings aufteilen, probiers aus !
delfiphan - Mo 21.03.05 13:01
Müsstest du aber noch ein Beispiel mitliefern; oder zu mindest sagen, was WordPos ist.
Man will 1 String in mehrere Strings zerteilen. Dabei soll man auch angeben können, welches Zeichen das Trennzeichen ist. Bei deiner Prozedur muss man irgendwie die Wortposition kennen, und man bekommt jeweils nur ein String zurück :?: Muss man die Prozedur für jeden Eintrag ausführen, und sich jeweils die Position merken? Muss man selbst prüfen, ob man am Ende des Strings ist? Wo geb ich das Trennzeichen an, muss ich da jedes mal den Source an mehreren Stellen ändern gehn? Was ist dann der Vorteil deiner Prozedur gegenüber Pos und Copy? ....
SchelmVomElm - Mo 21.03.05 13:07
Also wie das gehen soll ist mir auch nicht klar! Wenn WordPos in der Schleife nicht 0 erreicht hat die Funktion nicht mal einen definierten Rückgabewert! Also, was soll das?
F34r0fTh3D4rk - Mo 21.03.05 14:38
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22:
| Function WortExtrahieren(Text: string; Wort: Word; Trennzeichen: Char): string; var p : PChar; begin p := PChar(Text); repeat Dec(Wort); while p^ <> Trennzeichen do begin if Wort = 0 then Result := Result + p^; Inc(p); end; if Wort = 0 then Exit; Inc(p); until p^ = Trennzeichen; end;
str:= 'Hallo;Du;Da'; str2:= WortExtrahieren(str, 1, ';'); |
delfiphan - Mo 21.03.05 14:44
Mit dem Beispiel wird's schon viel klarer. :)
Scheint zu funktionieren, nur: Das letzte Wort lässt sich nicht korrekt extrahieren:
Delphi-Quelltext
1:
| WortExtrahieren('a;b;c',3,';'); |
Und: Wie weiss ich eigentlich, dass ich am Ende des Strings bin?
WortExtrahieren('a;b;c',4,';');gibt eine Endlosschleife. Ausserdem kann das String auch mal leer sein...
F34r0fTh3D4rk - Mo 21.03.05 14:47
ich habe gerade einen fehler in delphi enddeckt, ich habe ein wort per random auswählen und als showmessage anzeigen lassen, wenn das letzte wort ausgewählt wurde kommt kein msg fenster sondern ein formular mit unendlicher breite und links oben ein label auf dem das wort steht, ok button fehlt und X lässt sich auch net erreichen, weils nach rechts hin unendlich lang ist. :shock:
retnyg - Mo 21.03.05 14:48
wenn ich das richtig sehe wird bei dunkelfürchters code einfach der pointer erhöht, was ein speicherleck erzeugt, der PChar kann nicht mehr freigegeben werden weil der pointer nicht mehr passt
F34r0fTh3D4rk - Mo 21.03.05 14:50
ich glaube der fehler, dass das letzte wort net ausgelesen wird lässt sich so beheben:
delfiphan - Mo 21.03.05 14:52
Wollt ich soeben auch schreiben. @F34r0fTh3D4rk: Das ist kein Delphi-Fehler, sondern ein Folgefehler wegen deiner Prozedur. Auch wenn der Pointer korrekt vernichtet würde spuckt deine Prozedur Unsinn beim letzten Wort aus: Du testest nirgends auf das Ende des Strings!!
//Edit: Hab deinen Post erst jetzt gelesen. Lässt sich so nur bedingt beheben... Das ist doch keine Lösung ;) Woher soll man überhaupt wissen, wieviele Einträge der String hat? Die Strings kommen aus einer Datei, da kann eine Zeile auch mal leer sein!!
Wie dem auch sei: Die ursprüngliche Frage ist schon längst beantwortet. Lassen wir's sein!
F34r0fTh3D4rk - Mo 21.03.05 15:04
ich habs gerade so versucht, das ist aber schwachsinn, wie kann ich denn in meinem code das ende des strings abfragen ohne extra noch einen zähler einzubauen ?
Delphi-Quelltext
1:
| until (p^ = Trennzeichen) or (not (ord(p^) in [1..255])); |
delfiphan - Mo 21.03.05 15:08
p ist nullterminiert. Da brauchst du keinen Zähler. Du solltest aber eine while-Schleife benützen, da das erste Zeichen schon eine #0 sein kann.
Übrigens @retnyg: Gibt's wirklich ein Speicherleck? PChar liefert hier doch nur nen Zeiger auf Text zurück und alloziert keinen neuen Speicher.
//Edits 1,2: Sorry, komische Satzkonstruktionen geflickt ;)
F34r0fTh3D4rk - Mo 21.03.05 15:11
genau :D
retnyg - Mo 21.03.05 15:16
Zitat: |
Delphi-Quelltext 1: 2: 3:
| p : PChar; begin p := PChar(Text); | |
hier wird doch ein neuer PCHar erstellt, und der wert von text reinkopiert. danach wird der pointer "verbogen", wie soll der kompiler wissen was er nun wieder freigeben kann ?
opfer.der.genauigkeit - Mo 21.03.05 15:23
Wieso sollte das n Speicherleck erzeugen?
p ist der Zeiger auf den String.
Der String wird von Delphi eh seperat behandelt.
p = pchar(s) und d.h. p ist der zeiger von s .. wird also s, von Delphi, freigegeben ist der pointer eh müll..
Sinnvoll wäre da noch p = nil. Schöner wär's allerdings.
Versucht mal den pointer so freizugegeben Dispose(p) .. viel Spaß mit der Exception.
F34r0fTh3D4rk - Mo 21.03.05 15:25
Zitat: |
Sinnvoll wäre da noch p = nil. Schöner wär's allerdings.
|
wo ?
retnyg - Mo 21.03.05 15:26
opfer.der.genauigkeit hat folgendes geschrieben: |
Wieso sollte das n Speicherleck erzeugen?
p ist der Zeiger auf den String.
Der String wird von Delphi eh seperat behandelt. |
wäre p der zeiger auf einen string, würde das so aussehen:
Delphi-Quelltext
1: 2: 3:
| p : ^string; begin p := @Text; |
F34r0fTh3D4rk - Mo 21.03.05 15:26
so funktionier das aber leider net
opfer.der.genauigkeit - Mo 21.03.05 15:45
Ok,
ich seh's ein.. blöd formuliert. :oops:
Du hast recht retnyg.. ist kein zeiger auf string.
*sfz*
Ok, besser ausgedrückt.
p := pchar(s);
Ein PChar ist ein Zeiger auf einen nullterminierten String mit Zeichen des Typs Char.
p muß und kann nicht freigegeben werden in diesem fall, da s von delphi eh freigegeben wird.
p zeigt aber weiterhin auf den Text, da Delphi den Speicher nicht mit Nullen vollschreibt, sondern nur die Referenz von s tötet.
Naja.. deshalb p := nil am Ende setzen, sofern man das möchte.
Würde man z.B. das hier machen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| .. private globalP: pchar; .. var s: string; p: pchar; begin s := 'test'; p := pchar(s); globalP := p; end;
procedure irgendwas; begin showmessage(globalp); end; |
Naja, ich hoffe meine Aussagen stimmen, sonst muß ich mich wohl heute einbuddeln und nochmal das Thema mit den Zeigern durchkämpfen. :roll:
F34r0fTh3D4rk - Mo 21.03.05 15:49
oha, bin ich dumm, so muss es lauten:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
| Function WortExtrahieren(Text: string; Wort: Word; Trennzeichen: Char): string; var p : PChar; begin p:= PChar(Text); repeat Dec(Wort); while p^ <> Trennzeichen do begin if Wort = 0 then Result := Result + p^; if p^ = #0 then Exit; Inc(p); end; if Wort = 0 then Exit; Inc(p); until (p^ = Trennzeichen); P:= nil; end; |
SchelmVomElm - Mo 21.03.05 15:53
p ist ein Zeiger auf das erste Zeichen des Strings.
Der Speicher für den gesammten nullterm. string ist reserviert.
Nach der Benutzung gibt Delphi den Speicher wieder frei.
Und zwar von p bis #0. p hat sich aber verändert und ob der Compiler das merkt und entsprechend handelt ist hier die Frage!
Durchaus diskussionswürdig wie ich finde - ich glaub das gibt 'nen Leck!
F34r0fTh3D4rk - Mo 21.03.05 15:55
hier gehn die meinungen auseinander, wo ist der beweis ?
retnyg - Mo 21.03.05 16:03
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| procedure TForm1.Button1Click(Sender: TObject); var s: string; p:pchar; pp, ps: pointer; begin s:='bla'; p:=pchar(s); ps:=@s; pp:=@p; if ps <> pp then showmessage('uneven'); end; |
hier dran sieht man, dass die funktion PChar(String) zuerst einen neuen, null-terminierten string erzeugt und anschliessend darauf zeigt, es wird also nicht einfach ein pointer auf den bereits existierenden string erstellt.
F34r0fTh3D4rk - Mo 21.03.05 16:05
ja, wird dieser denn aber nicht trotzdem freigegeben ?
SchelmVomElm - Mo 21.03.05 16:07
Wenn ich einen hätte würd ich ihn auch posten. Und wenn man es schon nicht besser weiss, würde ich erst recht davon ausgehen dass ein Speicherleck gibt und mich drum kümmern. Gehört sich einfach so.
opfer.der.genauigkeit - Mo 21.03.05 16:07
Aber mit @ holst du dir den Offset der variable.
Klar, daß @p dann nicht gleich @s, das sind zwei völlig verschiedene Variablen.
Um so mehr, wird Delphi sich selbstständig um p kümmern und dabei spielt es keine Rolle wohin der Zeiger zeigt.
Achja, ganz nebenbei hier mal n Auszug aus der Hilfe:
Zitat: |
Ein PChar ist ein Zeiger auf einen nullterminierten String mit Zeichen des Typs Char. Jeder der drei Zeichentypen besitzt einen integrierten Zeigertyp:
PChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PAnsiChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PWideChar ist ein Zeiger auf einen nullterminierten String mit 16-Bit-Zeichen.
PChars bilden mit kurzen Strings den ursprünglichen String-Typ von Object Pascal. Sie wurden als Kompatibilitätstyp zur Sprache C und zur Windows-API eingeführt.
|
//Edit:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9:
| var s: string; p: pchar; begin s := 'test'; p := pchar(s);
if pointer(p) = pointer(s) then showmessage('gleich'); end; |
Ich verpeil eh grad alles.. *ne kippe rauchen geht*
SchelmVomElm - Mo 21.03.05 16:13
opfer.der.genauigkeit hat folgendes geschrieben: |
Aber mit @ holst du dir den Offset der variable.
Klar, daß @p dann nicht gleich @s, das sind zwei völlig verschiedene Variablen.
Um so mehr, wird Delphi sich selbstständig um p kümmern und dabei spielt es keine Rolle wohin der Zeiger zeigt.
Achja, ganz nebenbei hier mal n Auszug aus der Hilfe:
Zitat: |
Ein PChar ist ein Zeiger auf einen nullterminierten String mit Zeichen des Typs Char. Jeder der drei Zeichentypen besitzt einen integrierten Zeigertyp:
PChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PAnsiChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PWideChar ist ein Zeiger auf einen nullterminierten String mit 16-Bit-Zeichen.
PChars bilden mit kurzen Strings den ursprünglichen String-Typ von Object Pascal. Sie wurden als Kompatibilitätstyp zur Sprache C und zur Windows-API eingeführt.
|
//Edit:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| var s: string; p: pchar; begin s := 'test'; p := pchar(s);
if pointer(p) = pointer(s) then showmessage('gleich'); end; |
Ich verpeil eh grad alles.. *ne kippe rauchen geht* |
Der Sinn dieses Postings ist mir nicht klar - auch wenn ich mir dabei Zirkusmusik vorstelle! :mrgreen:
opfer.der.genauigkeit - Mo 21.03.05 16:30
Eigentlich bezieht sich das auf die letzte Aussage von retnyg
und soll ausdrücken, daß p hier nicht freigegeben werden muß.
retnyg - Mo 21.03.05 16:35
variablen werden vom delphi-compiler von haus aus selber freigegeben, mit Dispose gibt man Objekte frei.
aber woher soll der compiler wissen, wo der freizugebende pchar im speicher ist, wenn der zeiger drauf verändert wird ? ich glaub nicht dass für jede variable zwei pointer gespeichert werden.
delfiphan - Mo 21.03.05 17:11
Es kommt drauf an, wie der String gespeichert ist. Bei "hardcoded" Strings ist es anders als bei Strings, die intern mit GetMem erzeugt wurden. Hier einige Beispiele, die das verdeutlichen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| Var S : String; P : PChar; begin S := 'abcdefg'; P := PChar(S); S[2] := 'B'; ShowMessage(P); S := 'abcd'; S := S + 'efg'; P := PChar(S); S[2] := 'B'; ShowMessage(P); end; |
Siehe z.B. auch hier:
Reverse [
http://www.delphi-forum.de/viewtopic.php?p=222367#222367] (Hier wird ein PChar-Pointer ebenso verändert).
Ich wage mal zu behaupten, dass bei nicht hardgecodeten Strings gilt:
p := PChar(S) ist äquivalent zu
p := @S[1].
Könnte mich aber täuschen, das hier basiert lediglich auf Beobachtungen....
Übrigens hab ich oben (weiss nicht mehr wo) einen Denkfehler gesehn:
p ist natürlich nie gleich
@S!
Wenn
p am gleichen Ort gespeichert ist wie
S, dann gilt:
p=@S[1].
opfer.der.genauigkeit - Mo 21.03.05 17:41
retnyg hat folgendes geschrieben: |
variablen werden vom delphi-compiler von haus aus selber freigegeben. |
Jup, und was anderes als ne Variable ist es nicht.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| var p1, p2, p3, p4: pointer; pc: pchar; s : string; c1, c2: char; begin
s := 'TEST';
pc := pchar(s);
p1 := pointer(s); p2 := pointer(pc); p3 := @s; if p1 = pointer(p3^) then showmessage('gleich'); p4 := @pc; if p2 = pointer(p4^) then showmessage('gleich');
inc(pc); if @pc = p4 then showmessage('gleich');
end; |
Moderiert von
Tino: Delphi-Tags hinzugefügt.
SchelmVomElm - Mo 21.03.05 17:42
Zitat: |
p := PChar(S) ist äquivalent zu p := @S[1] |
Also wenn Du mit S einen Pascal string meinst kann das nicht sein, denn der muss keine Nullterminierung enthalten!
Delphi-Quelltext
1: 2:
| S := S + #0; p := @S[1]; |
delfiphan - Mo 21.03.05 17:49
Der normale String (= implizit AnsiString) ist nullterminiert, obwohl du das nicht zu spüren bekommst!
Der ist unter Umständen sogar doppelt nullterminiert (wegen den WideChars!).
Wenn du's nicht glaubst, siehe system.pas!
retnyg - Mo 21.03.05 17:56
fazit: in diesem speziellen fall wird kein speicherleck erzeugt (ausser ein hartgecodeter string wird DIREKT hergenommen, also nicht über einen prozedureaufruf), es ist aber gefährlich, zeigertypen herumzubiegen wenn man nicht genau weiss was man tut (und ich bin mir sicher dass das bei f34ar0fth3d4rk der fall war ;)), weswegen man es vermeiden sollte.
lieber manuell einen zeiger des typs pointer erstellen und dann mit diesem herumwerkeln...
F34r0fTh3D4rk - Mo 21.03.05 17:56
wenn man mehrere strings zusammenfügt, werden die nullen dann entfernt ?
kann ja sein, dass der string dadurch immer mehr bytes schluckt ?!
und der code war ja zuerst auch nur für das zeichen #0 gedacht, deswegen hats ja auch anfangs funktioniert, wenn man eigene trennzeichen nehmen will muss man das ende des strings extra abfragen, weil es nicht = trennzeichen ist
delfiphan - Mo 21.03.05 17:58
Natürlich werden die Nullen zuerst entfernt. Wenn du wüsstest, was alles abgeht, wenn man zwei Strings addiert... Du würdest staunen! ;)
F34r0fTh3D4rk - Mo 21.03.05 17:59
hatte bis jetzt noch nicht zeit und bock mir das anzuschauen, deshalb einige wissenslücken :D
delfiphan - Mo 21.03.05 18:05
Delphi-Quelltext
1: 2:
| S := 'Hallo '+A+' und '+B+' '+IntToStr(I); S := Format('Hallo %s und %s %d',[A,B,I]); |
Was denkst du, welche Variante ist effizienter? Du ahnst absolut richtig ;)
Zugegeben, IntToStr ruft Format auf, aber auch ohne IntToStr ist die zweite Methode schneller....
hansa - Mo 21.03.05 19:06
Daß mit festen Feldlängen sämtliche eventuell aufgetauchten Probleme gar nicht erst auftauchen würden, das merkt wohl keiner. 8) Das einzig brauchbare, was hier steht ist der Beitrag, von Delphifan, man könne bei Zahlen ruhig ein Trennzeichen verwenden.
Nur : wo liegt der Vorteil davon überhaupt ? Mir ist niemand bekannt, der sich heute noch auf CSV einläßt, nur weil in den 50er Jahren irgendjemand mal bei 8-Bit Zeichensätzen sich ein seltenes Zeichen dafür ausgedacht hat.
delfiphan - Mo 21.03.05 19:12
Bei festen Feldlängen gibt's dafür andere Probleme: Sie sind weniger gut editierbar, und es kann vorkommen, dass man plötzlich zu wenig Pla
retnyg - Mo 21.03.05 19:14
würde ich nicht sagen, csv ist immer noch die einfachste möglichkeit ne datenbank zu erstellen.
n paar werte mit 10 zeilen code in ne csv schreiben, die kann dann mit excel geöffnet werden und man hat alle werte in den richtigen spalten.
hansa - Mo 21.03.05 19:52
Ich gebe es bald auf. Angenommen 3 Integer stehen in einer Zeile. Jede hat 10 Stellen. Ein paar Werte auslesen aus einer Textdatei geht dann so :
nicht CSV :
Delphi-Quelltext
1: 2: 3:
| Zahl1 := StrToInt (copy (zeile,1,10)); Zahl2 := StrToInt (copy (zeile,11,10)); Zahl3 := StrToInt (copy (zeile,21,10)); |
mit CSV und
keiner festen Feldlänge sähe es z.B. so aus :
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| SemikolonPos := pos (';',Zeile); HilfStr := copy (zeile,1,SemikolonPos-1); Zahl1 := StrToInt (copy (HilfStr,1,10)); delete (zeile,1,SemikolonPos); SemikolonPos := pos (';',Zeile); HilfStr := copy (zeile,1,SemikolonPos-1); Zahl2 := StrToInt (copy (HilfStr,1,10)); delete (zeile,1,SemikolonPos); SemikolonPos := pos (';',Zeile); HilfStr := copy (zeile,1,SemikolonPos-1); Zahl3 := StrToInt (copy (HilfStr,1,10)); delete (zeile,1,SemikolonPos); |
Handelt es sich nicht um Zahlen, dann hat man sowieso wohl verloren, denn man stelle sich mal vor, irgendjemand stellt aus Versehen die Tastatur auf englisch um. Er will eingeben : "östlich" und wegen geringer Schreibmaschinenkenntnisse achtet er mehr auf die Tastatur als auf das was tatsächlich da steht. Und das ist dann ";stlich".
Jetzt kommt alles mitsamt unbewußten Schreibfehlern in eine Datei und das Programm achtet nur auf ; Da ist aber jetzt einer zuviel drin und das Programm läuft nicht bis zum Ende durch. Die bewußte Eingabe des Trennzeichens ist dabei noch völlig außer acht gelassen.
Nimmt man ein anderes "Trennzeichen", so wird sich kaum was ändern. Es kracht irgendwann doch.
Das Argument mit Excel ist übrigens auch nur Theorie. Das kommt mit falschen Zeichen in einer "CSV" Datei genauso wenig zurecht, wie jedes andere Programm auch.
Der nächste Nachteil ist, daß man im Fehlerfall einen Editor getrost vergessen kann. In einer Textdatei ein ; zuviel zu entdecken ist fast unmöglich.
retnyg - Mo 21.03.05 20:07
den zwoten codeteil kannst du dir sparen wenn du die explode funktion nimmst.
klar ist csv fehleranfällig wenn in texten semikolons vorkommen können.
wenn dies aber nie der fall sein wird, kann man das getrost verwenden.
bsp.: ich hatte mal ein ping-programm geschrieben das alle hosts eines subnetzes anpingt, und dann jeweils die hostnamen, ip-adresse und roundtrip time in ein csv schreibt.
die csv dann in excel geöffnet und schon hat man eine tabellierte übersicht aller rechner im netz.
delfiphan - Mo 21.03.05 20:20
Vollständigkeitshalber möchte ich noch darauf hinweisen, dass man Tab-Separated Files sehr einfach so einlesen kann:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| Var a, b, c : Integer begin AssignFile(F, 'test.txt'); reset(F); while not eof(F) do begin Read(F, a, b, c); end; CloseFile(F); end; |
Wie retnyg schon gesagt hat: Files, die Spalten durch ein Zeichen trennen, werden von Excel unterstützt und sind deswegen recht praktisch. Beim CSV Format kannst du deine Dateien sogar als .CSV abspeichern und durch Doppelklick direkt im Excel ansehn.
IngoD7 - Mo 21.03.05 20:27
Warum diskutieren, ob das csv-Format "im deutschsprachigen Raum" :lol: genutzt wird und was möglicherweise alles besser ist? Natürlich wird es genutzt!
Und wer es nutzt, wer also diese Dinger erstellt und liest, der sollte tunlichst das csv-Format kennen und korrekt implementieren. Es sind dabei bekanntermaßen das Semikolon ';' und die Anführungsstriche '"' gesondert zu beachten. Csv zu benutzen mag zuweilen etwas kompliziert und nicht in allen Fällen die erste Wahl sein, aber es ist möglich, durchaus noch uso (siehe Excel) und durchaus manchmal notwendig (siehe Anforderung Threadersteller).
P.S.: Ich habe mit dem csv-Format keinerlei Probleme und nutze es eigentlich immer, um Tabellen aus Excel heraus zu exportieren, wenn ich sie in eigenen Projekten weiterverarbeiten will.
hansa - Mo 21.03.05 20:43
retnyg hat folgendes geschrieben: |
...die csv dann in excel geöffnet und schon hat man eine tabellierte übersicht aller rechner im netz. |
Das ist ja schön und gut, aber Excel hat mit CSV absolut nichts zu tun.
delfiphan - Mo 21.03.05 20:46
hansa hat folgendes geschrieben: |
Das ist ja schön und gut, aber Excel hat mit CSV absolut nichts zu tun. |
Doch, das hat es. Exportier/Importier mal eine Exceltabelle. Wie würdest du es tun?
hansa - Mo 21.03.05 21:19
In Excel ? Wie gesagt : mit festen Feldlängen, ohne mich um die Trennzeichen kümmern zu müssen.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 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!