Autor |
Beitrag |
mb
      
Beiträge: 185
|
Verfasst: So 31.08.03 00:55
Hallo!
Ich möchte - ganz einfach - eine Textdatei lesen, den Inhalt modifizieren und in eine andere Datei schreiben. Das tue ich - schon seit TP 5 - ganz einfach, inzwischen in Delphi etwas abgewandelt (und bis Delphi 6 hatte es auch immer geklappt):
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12:
| AssignFile(f1, "file1.dat"); AssignFile(f2, "file2.dat"); Reset(f1); ReWrite(f2); while not eof(f1) do begin ReadLn(f1, s); s := ProcessThisStringProc(s); WriteLn(f2, s); end; CloseFile(f1); CloseFile(f2); |
So in etwa (!) sieht das aus...
Das Ergebnis ist: es kommt eine Datei heraus, die dem Unix-Format ähnelt, was ich in diesem Fall an den Zeilenumbrüchen feststelle... Auch mein Texteditor fragt, ob er die Datei ins DOS/Win-Format konvertieren soll.... Ich frag mich, wie das kommt. In der Datei sind nur ganz normale ASCII-Zeichen, bzw. sogar [0..9,a..z,A..Z].
Ich probier das gerade mit der Trial von Delphi 7; ist da was anders geworden??
Ich wollte zu diesem Zweck ungern auf kompliziertere Methoden zurückgreifen... oder gibt es eine andere gute Möglichkeit??
_________________ Gruß,
MB
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 31.08.03 05:58
Wie macht denn ProcessThisStringProc die Zeilenumbrüche? Ein Windows Zeilenumbruch sieht so aus: #13#10.
|
|
mb 
      
Beiträge: 185
|
Verfasst: So 31.08.03 11:03
Hallöle!
Ja, ich hätte mir denken können, das jemand nach dieser geheimnisvollen Prozedur fragt. ... Diesen Namen hatte ich einfach als Platzhalter eingesetzt. Es werden in wirklichkeit aber nur Zeichen(-ketten) meist am Anfang der Strings verändert.
Gehen wir davon aus, dass ich einfach mit der Funktion
Delphi-Quelltext 1:
| s := AnsiReplaceText(s, 'fröhlich', 'traurig'); |
den SubString "fröhlich" in "traurig" ersetzen möchte. Dann dürften ja in einem normalen Text auch nicht die Zeilenenden ersetzt werden...
...und die Sourcedatei ist ganz klar eine DOS-formatige Datei mit den Umbrüchen (#13#10).
Und... ich muss den "Unix"-Hinweis wieder zurücknehmen. Es entsteht eine Unicode-Datei (?!) ...jedenfalls werdne pro Zeichen 16Bit verwendet!
_________________ Gruß,
MB
|
|
Brueggendiek
      
Beiträge: 304
Win 98, Win98SE, Win XP Home
D5 Std
|
Verfasst: So 31.08.03 11:13
Hallo MB!
Da solltest Du mal die Onlinehilfe (F1) befragen, ob D7 vielleicht standardmäßig für Strings Widestrings einsetzt!
Die Verwendung von Strings ist ja beim Übergang von Turbo-Pascal auf Delphi schon mal geändert worden - in TP war STRING identisch mit STRING[255] - das muß man bei D5 als "Shortstring" deklarieren, während STRING jetzt "Ansistring" ist mit bis zu 2GB, mit 8 Bit pro Zeichen.
Möglich, daß bei D7 das auf "Widestring" geändet wurde - das ist der Unicode-String mit 16 Bits pro Zeichen!
Ist natürlich nur so eine Vermutung, aber bei dem Fehlerbild kann ich mir nichts anderes vorstellen.
Nimm doch eventuell mal die Umwandlung ganz raus, so daß ein reines Kopierprogramm entsteht - vielleicht bewirkt die Umwandlung ja auch den 16-Bit-Effekt.
Gruß
Dietmar Brüggendiek
|
|
MrSaint
      
Beiträge: 1033
Erhaltene Danke: 1
WinXP Pro SP2
Delphi 6 Prof.
|
Verfasst: So 31.08.03 12:19
hmmm... mit den Zeilenumbrüchen? also ich bin der meinung, dass das einzig und allein an dem "WriteLn(f2, s);" liegt. weil das macht ja noch nen Zelenumbruch. und ich mein "ReadLn" ließt den Zeielnumbruch gar nich mit, wenn ich mich recht daran erinnere. heißt, in "s" is nacher nich am schluß ein #13#10 und auch kein #13 (wie das bei Unix aussieht). also wenns nich an diesem Unicode liegt (wovon ich (zu meiner Schande) keine ahnung hab  ), dann liegt das an dem WriteLn meiner Ansicht nach...
MrSaint
_________________ "people knew how to write small, efficient programs [...], a skill that has subsequently been lost"
Andrew S. Tanenbaum - Modern Operating Systems
|
|
mb 
      
Beiträge: 185
|
Verfasst: So 31.08.03 12:29
Ja, dass es am WriteLn liegt dachte ich auch schon... Wie würdet ihr denn ne reine Textdatei auslesen und schreiben, wenn nicht mit ReadLn und WriteLn? Mit Write() kann ich ja keine untypisierte Datei schreiben, sonst hätt ich ja den Zeilenumbruch selbst dranhängen können.
Das mit AnsiString, WideString, ... werd ich noch mal prüfen.
Danke trotzdem soweit.
_________________ Gruß,
MB
|
|
MrSaint
      
Beiträge: 1033
Erhaltene Danke: 1
WinXP Pro SP2
Delphi 6 Prof.
|
Verfasst: So 31.08.03 12:32
es gibt ja noch die API Funktionen. ich glaub das waren fileopen(..), filewrite(..), fileread(...). geb aber keine garantie dafür, weil ich die datei-funktinen irgendwie immer durcheinander bring
MrSaint
_________________ "people knew how to write small, efficient programs [...], a skill that has subsequently been lost"
Andrew S. Tanenbaum - Modern Operating Systems
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: So 31.08.03 12:44
Es muß auch mit writeln gehen. Aber kuck mal, ob D7 nicht wirklich standardmäßig WideStrings nimmt.
|
|
Klabautermann
      

Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: So 31.08.03 13:03
Hallo,
Luckie hat folgendes geschrieben: | Es muß auch mit writeln gehen. Aber kuck mal, ob D7 nicht wirklich standardmäßig WideStrings nimmt. |
ich habe gerade mal ein wenig in mainer D7 hilfe gestöbert. Dieses könnte für mb interessant sein:
Delphi 7 Hilfe hat folgendes geschrieben: | Das reservierte Wort string funktioniert wie ein generischer Typbezeichner:
var S: string;
Hier wird beispielsweise die Variable S für einen String erstellt. Im voreingestellten Status {$H+} interpretiert der Compiler string als AnsiString (wenn auf das reservierte Wort keine Zahl in eckigen Klammern folgt). Bei Verwendung der Direktive {$H?} wird string als ShortString interpretiert. |
Danach wird nicht standarmäßig WideString verwendet.
Es gab ein paar änderungen an den StrUtils:
Delphi 7 Hilfe hat folgendes geschrieben: | Unit StrUtils
Die Unit StrUtils weist folgende Änderungen hinsichtlich der Unterstützung von Multibyte-Zeichensätzen (MBCS) auf:
- In älteren Versionen konnte an LeftStr, RightStr und MidStr nur ein AnsiString-Parameter übergeben werden. Der Rückgabewert war ebenfalls auf den Typ AnsiString beschränkt. Multibyte-Zeichensätze (MBCS) wurden nicht unterstützt. In der neuen Version wurde jede dieser Funktionen durch ein Paar überladener Funktionen ersetzt, von denen jeweils eine AnsiString-Parameter und -Rückgabewerte und die andere WideString-Parameter und Rückgabewerte unterstützt. MBCS-Strings werden von den neuen Funktionen verarbeitet. Aufgrund dieser Änderung ist Quelltext, in dem diese Funktionen zum Speichern und Abrufen von Byte-Werten in AnsiStrings eingesetzt werden, nicht mehr funktionsfähig und muss (unter Verwendung der nachstehend beschriebenen neuen Funktionen auf Byte-Ebene) umgeschrieben werden.
- Die neuen Funktionen LeftBStr, RightBStr und MidBStr werden für Operationen auf Byte-Ebene eingesetzt, die früher mithilfe von LeftStr, RightStr und MidStr implementiert wurden.
- Die neuen Funktionen AnsiLeftStr, AnsiRightStr und AnsiMidStr entsprechen den neuen Funktionen AnsiStr, LeftBtr, RightStr und MidStr, sind aber im Gegensatz zu diesen nicht mit WideString-Funktionen überladen.
Die Unit StrUtils enthält die neue Funktion PosEx für die Stringsuche. |
vieleicht ergeben sich dadraus konpflikte.
@MB du könntest ja sicherheitshalber mal versuchen, deinen String vor dem Schreiben zu Typecasten. Also so:
Delphi-Quelltext 1:
| WriteLn(f2, AnsiString(s)); |
Gruß
Klabautermann
|
|
mb 
      
Beiträge: 185
|
Verfasst: So 31.08.03 13:34
Danke für die Antworten. Dennoch, hier der nicht ganz erfolgreiche Zwischenstatus...
Ich habe folgendes probiert...
Delphi-Quelltext 1: 2: 3:
| {$H-} var s: String; {$H+} |
...kein Erfolg
Delphi-Quelltext
...kein Erfolg
Delphi-Quelltext 1:
| WriteLn(f2, AnsiString(s)); |
...kein Erfolg
Selbst, wenn ich die Datei nur kopiere mit
Delphi-Quelltext 1: 2:
| ReadLn(f1, s); WriteLn(f2, s); |
...kommt nix gutes dabei raus. Es liegt also nicht an der Bearbeitung des Strings...
Da bin ich nun ehrlich gesagt etwas ratlos.
Andere Frage: Falls ich doch andere Zugriffsmethoden benutzen würde, so müsste ich die Datei dennoch Zeilenweise auslesen können; das geht aber ja AFAIK nicht mit FileWrite() und FileRead() ... oder BlockRead(), etc... oder? Ich will ja kein Array/Puffer auslesen, sondern eben immer bis zum Zeilenende. (...und das müsste m.E. einfacher gehen, als einen Puffer zu lesen und dann auf ^M^J / #13#10 o.ä zu untersuchen)
_________________ Gruß,
MB
|
|
Klabautermann
      

Beiträge: 6366
Erhaltene Danke: 60
Windows 7, Ubuntu
Delphi 7 Prof.
|
Verfasst: So 31.08.03 14:28
Hallo,
du könntest ein Objekt vom Typ tStringList erzeugen, und dessen ReadFromFile und WriteToFile Methoden verwenden.
Über
Delphi-Quelltext
kannst du auf die einzelnen Zeilen zugreifen.
Aber dass mit dem ReadLn, WriteLn wundert mich.
Gruß
Klabautermann
|
|
recall
      
Beiträge: 449
|
Verfasst: So 31.08.03 23:02
Hallo,
von welchem Typ sind denn dein f1 bzw. f2 ? TextFile ?
Nicht: "file of String" , oder ??
(daran könnts liegen)
Viele Grüsse.
P.S.: Bei mir läufts einwandfrei  .
//EDIT: Habe auch D7 (vergessen)
|
|
mb 
      
Beiträge: 185
|
Verfasst: Mo 01.09.03 09:57
Ja, meine Deklaration in diesem Bereich ist/war
Delphi-Quelltext
(Das muss ja auch irgendwie so sein, dass mir ein ganz blöder Fehler unterlaufen ist... ?!)
Dennoch: File of String akzeptiert Delphi auch nicht. Früher unter TP/BP war das ja mit var f1,f2: Text; getan. Seit sich das geändert hat, habe ich es immer erfolgreich (!) mit TextFile gemacht...
Aber zurückzu "File of String". Der Compiler meckert, dass der Typ String eine Finalisierung braucht, die im File type nicht erlaubt ist.
Wenn ich stattdessen File of ShortString oder ... String[255] einsetze, dann erhalte ich in meiner ReadLn(f1, s) - Codezeile die Meldung, dass die Typen inkompatibel sind.
@Klabauterman: Danke für diesen Tipp. Ich werde den gleich mal probieren.
_________________ Gruß,
MB
|
|
mb 
      
Beiträge: 185
|
Verfasst: Mo 01.09.03 10:35
Na ja, irgendwie stell ich mich wohl blöd an... Ich glaub, an so einer einfachen Sache saß ich noch nie so lange...
Also, hab umgestellt auf TStringList ... etwa so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| var f: TStringList; . . . f := TStringList.Create; try f.LoadFromFile(fn); f.SaveToFile(ChangeFileExt(fn, '.bak')); finally f.Free; end; |
Das Ergebnis ist: die erzeugte Datei ist leer. Besser gesagt: Bei LoadFromFile passiert schlichtweg nichts, es wird kein Inhalt in die Stringliste gelesen...
_________________ Gruß,
MB
|
|
mb 
      
Beiträge: 185
|
Verfasst: Mo 01.09.03 10:37
recall hat folgendes geschrieben: | P.S.: Bei mir läufts einwandfrei |
Könntest Du mal einen Sourceabschnitt posten, der bei dir compiliert wird und auch "semantisch" korrekt funktioniert ?
_________________ Gruß,
MB
|
|
Motzi
      
Beiträge: 2931
XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
|
Verfasst: Mo 01.09.03 10:53
mb hat folgendes geschrieben: | Das Ergebnis ist: die erzeugte Datei ist leer. Besser gesagt: Bei LoadFromFile passiert schlichtweg nichts, es wird kein Inhalt in die Stringliste gelesen... |
Existiert die Datei? Was steht in der Datei drinnen?
_________________ gringo pussy cats - eef i see you i will pull your tail out by eets roots!
|
|
recall
      
Beiträge: 449
|
Verfasst: Mo 01.09.03 12:34
@mb: Ich habe den ersten Quelltext von dir genommen (natürlich ohne s := ProcessThisStringProc(s); ), mit var f1,f2: TextFile; und das ganze in ein Button-OnClick-Ereignis getan...
Dann noch eine existierende Textdatei rausgesucht, fertig.
Hat funktioniert.
Vielleicht ist irgendwas mit deiner unit "system" nicht richtig ?!
Vielleicht neu installieren ?
Hast du Windows ME ? Da funktionierte bei mir die ini-Fileverwaltung nicht  und auch einige andere Dateizugriffe murksten rum.
(Werde dazu noch einen Thread aufmachen  ).
Viele Grüsse.
|
|
barfuesser
      
Beiträge: 324
|
Verfasst: Mo 01.09.03 12:34
@mb: Hast Du Dir schon mal die Ursprungsdatei angesehen? Nicht das in dieser Datei schon der Fehler liegt.
barfuesser
|
|
mb 
      
Beiträge: 185
|
Verfasst: Mo 01.09.03 13:15
Hallo - erst noch mal "danke" für Eure Teilnahme / Beteiligung an meinem Problem...
...irgendwie hört sich das ganze lächerlich an und dennoch finde ich echt den Fehler nicht.
Zu den Fragen:
Ja, die Datei existiert. Ich habe es auch schon mit anderen testweise probiert. Die Funktion ist ja inzwischen nur auf das kopieren (einlesen und wieder schreiben) reduziert ... selbst das funktioniert nicht.
Im Original-Quelltext sind sowieso noch weitere try-catch-Blöcke (sorry: ...except  ) vorhanden. Also, wenn da ein Fehler auftreten würde, müsste ich es merken (Exception).
Ratlos....
_________________ Gruß,
MB
|
|
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 01.09.03 13:23
Beantworte doch mal bitte dir Frage von barfuesser!
|
|
|