Entwickler-Ecke
Sonstiges (Delphi) - Daten in einer txt Datei neu anordnen! *argh*!
LuckyStrike4life - Mo 22.09.03 11:24
Titel: Daten in einer txt Datei neu anordnen! *argh*!
Morgen,
ja - also es geht wieder mal um Daten.
Mir wurde eine 35,6 MB Große txt Datei gegeben und ich soll die Anordnung verändern. Es handelt sich bei den Daten um GPS vermessungen. Hier mal n kleiner Auszug:
Zitat: |
11.2500000000 53.7500000000 94
11.2502777778 53.7500000000 94
11.2505555556 53.7500000000 93
11.2508333333 53.7500000000 93
11.2511111111 53.7500000000 92
11.2513888889 53.7500000000 91
11.2516666667 53.7500000000 91
11.2519444444 53.7500000000 92
11.2522222222 53.7500000000 90
11.2525000000 53.7500000000 90
11.2527777778 53.7500000000 89
11.2530555556 53.7500000000 90
11.2533333333 53.7500000000 90
11.2536111111 53.7500000000 90
11.2538888889 53.7500000000 89
11.2541666667 53.7500000000 88
11.2544444444 53.7500000000 89
11.2547222222 53.7500000000 92
11.2550000000 53.7500000000 94
11.2552777778 53.7500000000 94
11.2555555556 53.7500000000 92
11.2558333333 53.7500000000 88
11.2561111111 53.7500000000 86
11.2563888889 53.7500000000 86
11.2566666667 53.7500000000 86
11.2569444444 53.7500000000 85
11.2572222222 53.7500000000 84
11.2575000000 53.7500000000 83 |
Jetzt zu dem richtigen Problem. Die ersten Zahlen (angefangen bei "11." bis zum Freizeichen) stehen für "x" die nächsten Zahlen (von "53" bis Freizeichen) für y und die letzten beiden stehen für "z".
So kann man damit im Matrixsystem arbeiten. Nun ist die Reihenfolge "x, y, z" aber nicht zugebrauchen sondern "y, x, z" wird benötigt.
Das heißt ich muss die erste Spalte mit der zweiten Spalte vertauschen. Und dann wieder als txt Datei ausgeben.
Habt ihr Ideen?
barfuesser - Mo 22.09.03 11:43
[no delphi]
gib mal unter Linux auf der Konsole folgende Zeile ein:
Quelltext
1:
| gawk '{ print $2 " " $1 " " $3 }' old.dat > new.dat |
old.dat - alte Datei
new.dat - die neue Datei mit der neuen Reihenfolge der Daten
Es könnte auch sein, daß Du statt gawk nur awk aufrufen mußt.
[/no delphi]
barfuesser
lambruco - Mo 22.09.03 11:51
Zeilenweise einlesen,
vertauschen
und schreiben.
Wo liegt das Problem ??
readln,writeln ein wenig stringverarbeitung.
Folgende Funktion könnte dir helfen:
(Bsp: Token(Zeile,' ',2) gibt dir den zweiten Eintrag (53.xxx)).
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 Token(sString : string; sDelim : string; nTokenNo : longint) : string; var sWork : string; sToken : string; nStringLen : longint; nDelimLen : longint; nDelimPos : longint; i : longint; begin sWork := sString; nStringLen := Length(sString); nDelimLen := Length(sDelim); for i := 1 to nTokenNo do begin nDelimPos := Pos(sDelim, sWork); if nDelimPos = 0 then nDelimPos := Length(sWork) + 1; sToken := Copy(sWork, 1, nDelimPos-1); sWork := Copy(sWork, nDelimPos + nDelimLen, nStringLen) end; Token := sToken; end; |
barfuesser - Mo 22.09.03 11:57
[ot]
Wenn ich die letzten beiden Postings vergleiche, weiß ich warum ich Linux und seine Tools so mag!
[/ot]
barfuesser
LuckyStrike4life - Mo 22.09.03 12:07
lambruco hat folgendes geschrieben: |
Zeilenweise einlesen,
vertauschen
und schreiben.
Wo liegt das Problem ??
readln,writeln ein wenig stringverarbeitung.
Folgende Funktion könnte dir helfen:
(Bsp: Token(Zeile,' ',2) gibt dir den zweiten Eintrag (53.xxx)).
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 Token(sString : string; sDelim : string; nTokenNo : longint) : string; var sWork : string; sToken : string; nStringLen : longint; nDelimLen : longint; nDelimPos : longint; i : longint; begin sWork := sString; nStringLen := Length(sString); nDelimLen := Length(sDelim); for i := 1 to nTokenNo do begin nDelimPos := Pos(sDelim, sWork); if nDelimPos = 0 then nDelimPos := Length(sWork) + 1; sToken := Copy(sWork, 1, nDelimPos-1); sWork := Copy(sWork, nDelimPos + nDelimLen, nStringLen) end; Token := sToken; end; | |
Aha,
also würde ich die Datei ganz normal laden lassen und dein Code auf ne OnpressButton Funktion legen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| procedure TMainForm.Button1Click(Sender: TObject); begin
SL := tStringList.Create;
Try SL.LoadFromFile ('c:\file.txt'); begin
[...]Dein Code [...]
end; Finally SL.Free; end; end; |
Aber leider geht mir dein Code nicht so ganz auf, könntest du ihn mir mal etwas erläutern, damit ich weiß wo genau ich eingreifen und verändern muss?
@barfuesser
Zitat: |
[no delphi]
gib mal unter Linux auf der Konsole folgende Zeile ein:
Code:
gawk '{ print $2 " " $1 " " $3 }' old.dat > new.dat
old.dat - alte Datei
new.dat - die neue Datei mit der neuen Reihenfolge der Daten
Es könnte auch sein, daß Du statt gawk nur awk aufrufen mußt.
[/no delphi]
barfuesser |
Linux hab ich leider hier auf Arbeit nicht, könnte ich aber zuhause ausprobieren.
Aber obs dann funktionieren wird, hm.. wie muss ich denn dann die neue Reihenfolge angeben?
lambruco - Mo 22.09.03 12:25
Ähem...
ein bisschen mehr musst du schon machen.
Deine Textdatei musst du zeilenweise einlesen: Stichwort readln
Du erhältst einen String, der genau einer Zeile entspricht.
Mit Hilfe der Funktion Token kannst du den String zerlegen
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| var x,y,z : String; begin x := Token (Zeile,' ',2) y := Token (Zeile,' ',1) z := Token (Zeile,' ',3) result := y + ' ' + x + ' ' + z; end; |
Anschliessend kannst du das Ergebnis in eine neue Textdatei schreiben:
Stichwort append, writeln
Ruhig mal die Hilfe von Delphi bemühen oder schick 50€, dann tipp ich es dir auch noch.
LuckyStrike4life - Mo 22.09.03 12:28
Okay Leude,
ich glaub mir ist heute mal selber die Lösung eingefallen. Umständlich, aber es geht.
Ich werde das Programm so schreiben, dass jede Zeile erkannt wird, und nach bestimmten Mengen an vergangenen Zeichen die Zahlen ausgelesen und in eine dBase Tabelle geschrieben werden.
Nun, ne dBase Datei ist keine txt Datei aber man kann sie in Excel einlesen lassen und dann als txt Datei ausgeben lassen.
Umständlich, aber es wird gehen :D . Bin ja mal froh das mir auch ab und zu selber ne Lösung einfällt.
Dennoch vielen Dank!
CenBells - Mo 22.09.03 12:28
HAllo LuckyStrike4Life,
also, was hast du aus der letzten aufgabe gelernt?
LuckyStrike4Life hat folgendes geschrieben: |
Wie ist es zu realesieren das alle Zeilen abgearbeitet werden. Schon klar das ich dafür eine Schleife brauche ... allerdings ist mir nicht klar wie dies umzusetzen ist. |
Also kommst du mit deinem bisherigen ansatz
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| SL := tStringList.Create;
Try SL.LoadFromFile ('c:\file.txt'); begin
[...]Dein Code [...]
end; Finally SL.Free; end; end; |
nicht weiter. Dann verarbeitest du wieder nur eine Zeile.
Der Code von lambruco liefert dir, mit dem entsprechenden aufruf (bsp hat er angegeben), immer die koordinatenzahl - entweder x: ntoken=1 etc.
Was du also brauchst ist eine Schleife, dir nach dem laden in die stringlist alle items durchgeht.
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: 41: 42: 43:
| function Token(sString : string; sDelim : string; nTokenNo : longint) : string; var sWork : string; sToken : string; nStringLen : longint; nDelimLen : longint; nDelimPos : longint; i : longint; begin sWork := sString; nStringLen := Length(sString); nDelimLen := Length(sDelim); for i := 1 to nTokenNo do begin nDelimPos := Pos(sDelim, sWork); if nDelimPos = 0 then nDelimPos := Length(sWork) + 1; sToken := Copy(sWork, 1, nDelimPos-1); sWork := Copy(sWork, nDelimPos + nDelimLen, nStringLen) end; end; ...
... var LTempStr: String; LRowNr: Integer; begin SL := tStringList.Create;
Try SL.LoadFromFile ('c:\file.txt'); for LRowNr := 0 to sL.count - 1 do begin SL[LRowNr] := Token(SL[LRowNr], ' ', 2) + ' ' + Token(SL[LRowNr], ' ', 1) + ' ' + Token(SL[LRowNr], ' ', 3); end; SL.saveToFile('C:\file2.txt'); Finally SL.Free; end; end; |
Gruß
Ken
CenBells - Mo 22.09.03 12:29
edit: Sorry, war ein doppelpost
edit2: Super, ganze arbeit umsonst :evil:
lambruco - Mo 22.09.03 12:34
Würde klappen, aber eine Stringliste mit knapp 40 MB ??
Könnte ein bißchen schwerfällig sein, oder ?
CenBells - Mo 22.09.03 12:38
lambruco hat folgendes geschrieben: |
Würde klappen, aber eine Stringliste mit knapp 40 MB ??
Könnte ein bißchen schwerfällig sein, oder ? |
Von leichtfüssigem code war auch keine rede 8) :lol:
Ich würde es wohl auch mittels readln und writeln lösen, aber er wollte nun mal wieder mit ner stringlist arbeiten *G*
Gruß
KEn
barfuesser - Mo 22.09.03 12:40
LuckyStrike4life hat folgendes geschrieben: |
wie muss ich denn dann die neue Reihenfolge angeben? |
Wie oben angegeben! Bei awk ist der RecordSeparator auf ein Leerzeichen voreingestellt. in $0 steht die gesamte Zeile, in $1 die erste Spalte, in $2 die zweite usw. Mit 'print $2 $1 $3' werden also die 3 Spalten in der von Dir gewünschten Reihenfolge ausgegeben. Sie stehen dann aber ohne Trennzeichen hintereinander. Deshalb habe ich in obigen Code wieder jeweils ein Leerzeichen eingefügt. Nun die Ausgabe in eine neue Datei umleiten und fertig bist Du. Wie Du sehen kannst ein wunderschöner kleiner Einzeiler. Und die Zeit, die er eventuell während der Ausführung länger als ein compiliertes Programm benötigt, sparst Du locker bei der "Programmierung"!
Übrigens gibt es mit den CygWin-Tools eine komplette Linux-Shell für Windows, bei der die ganzen schönen Tools von awk über perl bis sed vorhanden sind.
barfuesser
smiegel - Mo 22.09.03 14:11
Hallo,
wie wäre es damit?
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure Tausche; var tin, tout:Textfile; lese:String; begin AssignFile(tin, 'c:\quelle.txt'); AssignFile(tout, 'c:\ziel.txt'); Reset(tin); Rewrite(tout); while not Eof(tin) do begin ReadLn(tin, lese); WriteLn(tout, Copy(lese, 15, 13), ' ', Copy(lese(1, 13), ' ', Copy(lese, 29, Length(lese)-28)); end; CloseFile(tout); CloseFile(tin); end; |
Der Code geht von der Annahme aus, dass die Länge der x- und y-Koordinaten gleich lang ist (13 Zeichen).
LuckyStrike4life - Mo 22.09.03 14:11
CenBells hat folgendes geschrieben: |
edit: Sorry, war ein doppelpost
edit2: Super, ganze arbeit umsonst :evil: |
Vielen Dank, CenBells -
du bist immer sogut und weise zu mir. Eventuell komme ich auch noch auf deinen Code zurück!
Werde jetzt mal die Linux Lösung von Barfuesser probieren, wenn denn mein Arbeitsrechner Knoppix frist. Hab meine Mittagspause extra genutzt um nach hause zu fahren und Knoppix zu suchen.
Was ich noch gerne wissen würde, wie kann ich in einer Schleife, die eine IF Anweisung ausführt - zwei Bedingungen ablaufen lassen? D.h. wenn die IF mit ja beantwortet wird, sollen mehrere Dinge abgearbeitet werden.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| For Idx := 0 To SL.Count -1 Do begin
If Copy (Sl[Idx], 1, 2) = '11' Then begin gesuchterWert := copy(sl[idx], 0, 15); xyztabelle.Append; xyztabelle.FieldByName('x').AsString := gesuchterWert; xyztabelle.Post;
end; |
Also es müsste nochmals
Delphi-Quelltext
1: 2: 3: 4:
| gesuchterWert := copy(sl[idx], 0, 15); xyztabelle.Append; xyztabelle.FieldByName('x').AsString := gesuchterWert; xyztabelle.Post; |
kommen. Natürlich in leicht abgeänderter Form, sonst würde es kaum sinn machen.
Könnte mir das mal jemand verraten?
smiegel - Mo 22.09.03 14:14
Irgendwie ging gerade etwas mit einem nächträglichen Edit in die Hose. Diese Eintrag bitte löschen.
LuckyStrike4life - Mo 22.09.03 14:48
smiegel hat folgendes geschrieben: |
Hallo,
wie wäre es damit?
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17:
| procedure Tausche; var tin, tout:Textfile; lese:String; begin AssignFile(tin, 'c:\quelle.txt'); AssignFile(tout, 'c:\ziel.txt'); Reset(tin); Rewrite(tout); while not Eof(tin) do begin ReadLn(tin, lese); WriteLn(tout, Copy(lese, 15, 13), ' ', Copy(lese(1, 13), ' ', Copy(lese, 29, Length(lese)-28)); end; CloseFile(tout); CloseFile(tin); end; |
Der Code geht von der Annahme aus, dass die Länge der x- und y-Koordinaten gleich lang ist (13 Zeichen). |
Ahhh Sniegel!
Das ist richtig! Du bist mein Held!! Danke, vielen Dank!
Auch bei den anderen bedanke ich mich. Sehr geht, Leute! Ich mag eure Bereitschaft zur Hilfe!!
Und natürlich mein dicken Respekt an Sniegel, vielleicht sollte ich mich Sniegel4life nennnen? :D
Na dann, bis bald!
smiegel - Mo 22.09.03 15:57
Hallo LuckyStrike4life,
Danke für das Lob.
Bloss ist Dir ein kleiner Fehler unterlaufen: ich nenne mich Smiegel und nicht Sniegel ;-)
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!