Autor |
Beitrag |
gerd8888
      
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: Sa 09.07.11 15:14
Hallo,
ich schreibe in einer Datei of char das Wort 'Hallo'
datei: file of char
Das ist nun in der textdatei.txt mit einem texteditor zu sehen.
Wenn ich aber nun diese Datei mit der TStringlist bearbeite: loadfromfile(textdatei.txt) und diese dann TStringlist.text
ausleseen will, kommt anstatt 'Hallo' der Buchstabe 'E'.
Wenn ich hinterher, die textdatei.txt mit einem texteditor oeffne und abspeichere, funktioniert alles.
Aber ich will nicht jedesmal die Datei oeffnen und abspeichern. Daher die Frage, wie kann man das Problem loesen?
Gerd
|
|
jaenicke
      
Beiträge: 19311
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 09.07.11 15:34
In Anbetracht der Fülle an Informationen (keine Delphiversion im Profil, kein Quelltext, ...) rate ich einmal ein wenig...
Ich vermute du hast Delphi 2009 oder höher. Heißt Char ist ein Unicodezeichen. Dann fehlt dir das Byte-Order-Mark am Anfang der Datei.
Wozu überhaupt die Spielerei mit file of char? Warum machst du es nicht gleich richtig, sei es nun mit einer TStringList oder anders? 
|
|
gerd8888 
      
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: Sa 09.07.11 16:11
Ich benutzte Delphi 2009.
Ich will folgendes machen: Ich will Daten speichern, Name... Text ... usw.
Normalerweise waehlt man die typisierte Form mit record. Das Problem hierbei ist, dass der Text unterschiedliche Groesse hat.
Einmal ist er nur 3 Zeichen und beim andernmal 10000 Zeichen lang. Also ist ein text:string[10000] nicht die sinnvollste Loesung.
Deshalb will alles in einer typisierten file of char schreiben. (Man kann auch mit seek Buchstabe fuer Buchstabe schnell auslesen)
Anfangs- und Endposition speichere ich in einer anderen typisierten Datei ab. Darum brauche ich das File of char.
Das ist das Spielchen, das ich gerade mache. Somit ist es praktisch dynamisch typisiert.
Wie setze ich den Byte-Order-Mark?
Gerd
|
|
jaenicke
      
Beiträge: 19311
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 09.07.11 16:21
Das BOM brauchst du nur, wenn du eine normal lesbare Unicodetextdatei erstellen willst. Wenn du die Daten einfach nur speichern willst, brauchst du das nicht, dann ist es aber auch vollkommen egal, dass du die Datei im Editor nicht lesen kannst.
Nimm einfach einen TFileStream zur Datenspeicherung. Dazu jeweils Klassen, in denen du die Daten hast, mit je einer Methode LoadFromStream zum Laden der Daten und SaveToStream zum Speichern der Daten in einenTStream, fertig.
gerd8888 hat folgendes geschrieben : | Normalerweise waehlt man die typisierte Form mit record. |
Du vielleicht, ich mit Sicherheit nicht. 
|
|
gerd8888 
      
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: Sa 09.07.11 17:05
Wie speicherst Du Daten ab, die Du schnell wieder finden möchtest?
Wenn Du das ganze nur als Textdatei abspeicherst, musst du jedesmal mit readln() dich Zeile für Zeile durchschlagen.
Und andere Methoden kenne ich nicht.
|
|
haentschman
      
Beiträge: 285
Erhaltene Danke: 33
DX10 Berlin Professional
|
Verfasst: Sa 09.07.11 17:14
Zitat: | Wie speicherst Du Daten ab, die Du schnell wieder finden möchtest? |
... in ner Datenbank ?
Zitat: | Ich will Daten speichern, Name... Text ... usw. |
... der Klassiker.
PS: Je nach Datenmenge und Zugriff kommen diverse DB in Frage. Persönlich würde ich auch bei wenig Datensätzen diese Variante vorziehen, da man sich über das Speichern (wo / wie) keine Gedanken machen muß. Letztendlich holt man sich die Informationen raus wie man sie braucht.

|
|
jaenicke
      
Beiträge: 19311
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 09.07.11 17:30
Ich benutze da in der Regel wie gesagt einen einfachen TFileStream. Gerade wenn es um extrem schnelle Zugriffe mit genau definierten Daten geht, kann das deutlich schneller als eine general purpose Datenbank sein.
Die allgemeine Methode ist aber wie bereits genannt wurde einfach eine Datenbank wie SQlite für kleinere Projekte oder Firebird (Embedded) für größere Projekte.
Meine Lösung sähe so ca. aus, wenn du keine echte Datenbank nutzen möchtest: 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: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75:
| type TMyData = class private FTest: string; FValue: Integer; public procedure SaveToStream(AStream: TStream); procedure LoadFromStream(AStream: TStream); property Test: string read FTest write FTest; property Value: Integer read FValue write FValue; end;
[...]
function LoadStringFromStream(AStream: TStream): String; var ResultString: AnsiString; StringSize: Integer; begin Result := ''; if AStream.Size - AStream.Position < SizeOf(StringSize) then Exit; AStream.ReadBuffer(StringSize, SizeOf(StringSize)); SetLength(ResultString, StringSize); if AStream.Size - AStream.Position < StringSize then Exit; AStream.ReadBuffer(Pointer(ResultString)^, StringSize); {$ifdef UNICODE} Result := Utf8ToString(ResultString); {$else} Result := Utf8Decode(ResultString); {$endif} end;
procedure SaveStringToStream(AStream: TStream; AString: String); var StringSize: Integer; StringToSave: AnsiString; begin StringToSave := Utf8Encode(AString); StringSize := Length(StringToSave); AStream.WriteBuffer(StringSize, SizeOf(StringSize)); AStream.WriteBuffer(Pointer(StringToSave)^, StringSize); end;
procedure TMyData.LoadFromStream(AStream: TStream); begin FTest := LoadStringFromStream(AStream); AStream.ReadBuffer(FValue, SizeOf(FValue)); end;
procedure TMyData.SaveToStream(AStream: TStream); begin SaveStringToStream(AStream, FTest); AStream.WriteBuffer(FValue, SizeOf(FValue)); end;
var FileContents: TFileStream; MyTest: TMyData; begin FileContents := TFileStream.Create(...); try MyTest := TMyData.Create; try MyTest.Test := 'blabla'; MyTest.SaveToStream(FileContents); finally MyTest.Free; end; finally FileContents.Free; end; end; | Das lässt sich natürlich noch beliebig schachteln usw.
Zum Beispiel in einer generischen Liste von Daten: 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:
| type TMyDataList = class(TObjectList<TMyData>) public procedure SaveToStream(AStream: TStream); procedure LoadFromStream(AStream: TStream); end;
[...]
procedure TMyDataList.LoadFromStream(AStream: TStream); var CurrentData: TMyData; i, DataCount: Integer; begin AStream.ReadBuffer(DataCount, SizeOf(DataCount)); for i := 0 to DataCount - 1 do begin CurrentData := TMyData.Create; CurrentData.LoadFromStream(AStream); end; end;
procedure TMyDataList.SaveToStream(AStream: TStream); var CurrentData: TMyData; begin AStream.WriteBuffer(Count, SizeOf(Count)); for CurrentData in Self do CurrentData.SaveToStream(AStream); end; | Ungetestet im Browser getippt, Tippfehler schenke ich dir. 
|
|
gerd8888 
      
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: Sa 09.07.11 19:39
Du musst aber bei TFileStream auch beim schreiben vorher mit sizeof(..) ihm die Groesse mitteilen.
Somit ist es vom Prinzip auch typisiert!
Es ist jetzt praktisch verschlüsselt (ist das eine Art Binärdatei?) in der Datei.
Das ist doch so gesehen der einzige Unterschied.
Schade, dass er das nicht wie eine textdatei speichert. Oder geht das auch?
Deinen Code würde ich ja gerne mal testen, leider bin ich mit TFileStream noch ungeübt.
|
|
jaenicke
      
Beiträge: 19311
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Sa 09.07.11 20:54
|
|
gerd8888 
      
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: So 10.07.11 13:31
Ich habe gerade versucht Deinen Code einzubauen.
Funktioniert bei mir nicht. Was ist falsch:
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: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private FTest: string; FValue: Integer; public procedure SaveToStream(AStream: TStream); procedure LoadFromStream(AStream: TStream); property Test: string read FTest write FTest; property Value: Integer read FValue write FValue; end;
var Form1:TForm1;
implementation
{$R *.dfm}
function LoadStringFromStream(AStream: TStream): String; var ResultString: AnsiString; StringSize: Integer; begin Result := ''; if AStream.Size - AStream.Position < SizeOf(StringSize) then Exit; AStream.ReadBuffer(StringSize, SizeOf(StringSize)); SetLength(ResultString, StringSize); if AStream.Size - AStream.Position < StringSize then Exit; AStream.ReadBuffer(Pointer(ResultString)^, StringSize); {$ifdef UNICODE} Result := Utf8ToString(ResultString); {$else} Result := Utf8Decode(ResultString); {$endif} end;
procedure SaveStringToStream(AStream: TStream; AString: String); var StringSize: Integer; StringToSave: AnsiString; begin StringToSave := Utf8Encode(AString); StringSize := Length(StringToSave); AStream.WriteBuffer(StringSize, SizeOf(StringSize)); AStream.WriteBuffer(Pointer(StringToSave)^, StringSize); end;
procedure TForm1.Button1Click(Sender: TObject); var FileContents: TFileStream; MyTest: TForm1; path, path_f:string; begin path := ExtractFilePath(ParamStr(0)); path_f:=path+'datei1.txt'; FileContents := TFileStream.Create(path_f,fmopenreadwrite); try MyTest := TForm1.Create; try MyTest.Test := 'blabla'; MyTest.SaveToStream(FileContents); finally MyTest.Free; end; finally FileContents.Free; end; end;
procedure TForm1.LoadFromStream(AStream: TStream); begin FTest := LoadStringFromStream(AStream); AStream.ReadBuffer(FValue, SizeOf(FValue)); end;
procedure TForm1.SaveToStream(AStream: TStream); begin SaveStringToStream(AStream, FTest); AStream.WriteBuffer(FValue, SizeOf(FValue)); end;
end. |
|
|
jaenicke
      
Beiträge: 19311
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 10.07.11 14:35
Was heißt "funktioniert nicht"? Meinst du den fehlenden Parameter beim TForm.Create?
Davon abgesehen ist es Quatsch das in das Formular einzubauen. Du willst ja nicht das Formular neu erzeugen und speichern sondern deine Daten...
Kopiere doch einfach den Quelltext wirklich 1:1...  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: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TMyData = class private FTest: string; FValue: Integer; public procedure SaveToStream(AStream: TStream); procedure LoadFromStream(AStream: TStream); property Test: string read FTest write FTest; property Value: Integer read FValue write FValue; end;
TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private public end;
var Form1:TForm1;
implementation
{$R *.dfm}
function LoadStringFromStream(AStream: TStream): String; var ResultString: AnsiString; StringSize: Integer; begin Result := ''; if AStream.Size - AStream.Position < SizeOf(StringSize) then Exit; AStream.ReadBuffer(StringSize, SizeOf(StringSize)); SetLength(ResultString, StringSize); if AStream.Size - AStream.Position < StringSize then Exit; AStream.ReadBuffer(Pointer(ResultString)^, StringSize); {$ifdef UNICODE} Result := Utf8ToString(ResultString); {$else} Result := Utf8Decode(ResultString); {$endif} end;
procedure SaveStringToStream(AStream: TStream; AString: String); var StringSize: Integer; StringToSave: AnsiString; begin StringToSave := Utf8Encode(AString); StringSize := Length(StringToSave); AStream.WriteBuffer(StringSize, SizeOf(StringSize)); AStream.WriteBuffer(Pointer(StringToSave)^, StringSize); end;
procedure TForm1.Button1Click(Sender: TObject); var FileContents: TFileStream; MyTest: TMyData; path, path_f: string; begin path := ExtractFilePath(ParamStr(0)); path_f := path + 'datei1.txt'; FileContents := TFileStream.Create(path_f, fmOpenReadWrite); try MyTest := TMyData.Create; try MyTest.Test := 'blabla'; MyTest.SaveToStream(FileContents); finally MyTest.Free; end; finally FileContents.Free; end; end;
procedure TMyData.LoadFromStream(AStream: TStream); begin FTest := LoadStringFromStream(AStream); AStream.ReadBuffer(FValue, SizeOf(FValue)); end;
procedure TMyData.SaveToStream(AStream: TStream); begin SaveStringToStream(AStream, FTest); AStream.WriteBuffer(FValue, SizeOf(FValue)); end;
end. |
|
|
gerd8888 
      
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: So 10.07.11 16:08
ja danke, so funktioniert es bei mir. Mir war schon klar, dass ich da wieder was falsch gemacht habe.
Du hast gesagt, dass man das auch als Text speichern könnte. Was muss man ändern.
Ich habe Dir ja gesagt, dass ich mich mit dem TStream nicht auskenne.
Du schreibst also mit writebuffer und liest mit readbuffer aus. Das habe ich verstanden.
Jetzt habe ich lediglich nur einen String abgespeichert.
Jetzt will ich einen Datensatz bestehend aus 2 Edit-Feldern abschliessend mit Button2 erzeugen
1 Name1
2 Name2
und dann den 2. Datensatz auslesen. Kannst Du weiterhelfen?
Da ich das Prinzip nicht kenne eine Frage:
Bei einer Datenbank mit Tstringlist muss ich die gesamten Daten in den Speicher laden.
Das muss ich bei TFileStream nicht? Ich kann hier direkt von der Datei den gewünschten Bereich auslesen?
Und wie sieht das beim speichern aus. Muss man da vorher die gesamte Datei oeffnen?
Gerd
|
|
jaenicke
      
Beiträge: 19311
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: So 10.07.11 17:11
gerd8888 hat folgendes geschrieben : | Du hast gesagt, dass man das auch als Text speichern könnte. Was muss man ändern. |
Naja, dann musst du dir überlegen in welchem Format du speichern möchtest (UTF-8, Unicode, ...) und dann entweder entsprechend umwandeln (UTF-8 ) oder das Byte-Order-Mark als erstes in die Datei schreiben, wenn die leer ist (Unicode).
gerd8888 hat folgendes geschrieben : | Jetzt will ich einen Datensatz bestehend aus 2 Edit-Feldern abschliessend mit Button2 erzeugen
1 Name1
2 Name2
und dann den 2. Datensatz auslesen. Kannst Du weiterhelfen? |
Du meinst wie du an den zweiten Datensatz kommst? Das lässt sich auf verschiedene Arten machen, je nach Datenmenge.
Du kannst z.B. einen Dateiheader als erstes speichern, in dem du nicht nur Metadaten über die Datei speicherst (Version, Datenanzahl, ...), sondern auch ein Inhaltsverzeichnis. Dann kannst du darüber direkt auf die Daten zugreifen. Das lohnt aber nur bei größeren Datenmengen.
Wenn es sehr schnell sein soll, bietet sich evtl. auch ein Zugriff via Memory-Mapped-Files an.
gerd8888 hat folgendes geschrieben : | Da ich das Prinzip nicht kenne eine Frage:
Bei einer Datenbank mit Tstringlist muss ich die gesamten Daten in den Speicher laden. |
Ja, grundsätzlich, dafür kannst du im Speicher aber auch Einträge zwischen anderen hinzufügen und löschen.
gerd8888 hat folgendes geschrieben : | Das muss ich bei TFileStream nicht? Ich kann hier direkt von der Datei den gewünschten Bereich auslesen? |
Ja, sicher. Dafür kannst du Position setzen und ab dort lesen. Du musst nur wissen wo die Position ist, eben z.B. durch ein Inhaltsverzeichnis.
gerd8888 hat folgendes geschrieben : | Und wie sieht das beim speichern aus. Muss man da vorher die gesamte Datei oeffnen? |
Wenn du in der Mitte einen Eintrag änderst, bleiben zwei Möglichkeiten:
Entweder ab der entsprechenden Position auslesen und den Rest neu speichern oder den Eintrag als gelöscht markieren und einfach anhängen. Das geht natürlich nur, wenn die Dateigröße auch ein wenig größer werden darf und es reicht die Datei ab und zu zu optimieren. Zudem darf die Datenreihenfolge keine Rolle spielen.
Bei neu Einfügen ebenso:
Wenn die Reihenfolge keine Rolle spielt, kann der Eintrag einfach angehängt werden.
Allgemein noch zur Wahl der Zugriffsmethode:
Wenn die Datenmenge so groß wird, dass ein komplettes Einlesen der Datei zu lange dauert, bietet sich vermutlich eher eine echte Datenbank an...
Diese Art der einfachen Speicherung in einer Datei bietet sich immer dort an, wo die Daten beim Start komplett in den Arbeitsspeicher geladen werden und dann zwischendurch oder am Ende wieder gespeichert werden.
|
|
gerd8888 
      
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: Mo 11.07.11 15:50
Zitat: | Naja, dann musst du dir überlegen in welchem Format du speichern möchtest (UTF-8, Unicode, ...) und dann entweder entsprechend umwandeln (UTF-8 ) oder das Byte-Order-Mark als erstes in die Datei schreiben, wenn die leer ist (Unicode). |
Ich würde es am liebsten so haben, dass ich es auch mit einem texteditor öffnen kann.
Was eignet sich da? UTF-8?
Und was muss ich dann einfügen?
|
|
jaenicke
      
Beiträge: 19311
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Mo 11.07.11 16:35
Naja, das kommt eben drauf an wie du es in der Datei haben willst... Woher soll ich das denn wissen?  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: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TMyData = class private FTest: string; FValue: Integer; public procedure SaveToStream(AStream: TStream); property Test: string read FTest write FTest; property Value: Integer read FValue write FValue; end;
TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private public end;
var Form1:TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); const ByteOrderMark: WORD = $FEFF; var FileContents: TFileStream; MyTest: TMyData; path, path_f: string; InitFile: Boolean; begin path := ExtractFilePath(ParamStr(0)); path_f := path + 'datei1.txt'; InitFile := not FileExists(path_f); if InitFile then FileContents := TFileStream.Create(path_f, fmCreate) else FileContents := TFileStream.Create(path_f, fmOpenReadWrite); try if InitFile then FileContents.WriteBuffer(ByteOrderMark, SizeOf(ByteOrderMark)) else FileContents.Position := FileContents.Size; MyTest := TMyData.Create; try MyTest.Test := 'blabla'; MyTest.SaveToStream(FileContents); finally MyTest.Free; end; finally FileContents.Free; end; end;
procedure TMyData.SaveToStream(AStream: TStream); var CurrentData: string; begin CurrentData := '"' + FTest + '";"' + IntToStr(FValue) + '"' + sLineBreak; AStream.WriteBuffer(PChar(CurrentData)^, Length(CurrentData) * SizeOf(Char)); end;
end. | Du kannst natürlich auch das CSV-Format als solches implementieren oder das ganz anders speichern... wie du eben möchtest...
|
|
gerd8888 
      
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: Mi 13.07.11 22:59
Das funktioniert bei mir. So habe ich es mir vorgestellt.
AStream.WriteBuffer(PChar(CurrentData)^, Length(CurrentData) * SizeOf(Char));
Du hast doch jetzt hier keine konkrete Laengenangabe. Wenn ich jetzt nur in einer Zeile so reinschreibe, dann lege ich mir ein Inhaltsverzeichnis an. Und dann kann ich, wenn ich Dich richtig verstanden habe mit Position jedes Element ausfindig machen.
Wie würdest Du das machen?
Und Dein sLineBreak;
Bringt der was von der Suche. Kann man dann auch irgendwie Zeilen auslesen?
|
|
gerd8888 
      
Beiträge: 205
Erhaltene Danke: 3
Win7
Delphi 10.1 Starter (kostenlos) Lazarus
|
Verfasst: Do 14.07.11 00:32
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: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131:
| unit Unit1;
interface
uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
type TMyData = class private FTest: string; FValue: Integer; public procedure SaveToStream(AStream: TStream); procedure LoadFromStream(AStream: TStream); property Test: string read FTest write FTest; property Value: Integer read FValue write FValue; end;
TForm1 = class(TForm) Button1: TButton; Button2: TButton; Label1: TLabel; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private public end;
var Form1:TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject); const ByteOrderMark: WORD = $FEFF; var FileContents: TFileStream; MyTest: TMyData; path, path_f: string; InitFile: Boolean; begin path := ExtractFilePath(ParamStr(0)); path_f := path + 'datei1.txt'; InitFile := not FileExists(path_f); if InitFile then FileContents := TFileStream.Create(path_f, fmCreate) else FileContents := TFileStream.Create(path_f, fmOpenReadWrite); try if InitFile then FileContents.WriteBuffer(ByteOrderMark, SizeOf(ByteOrderMark)) else FileContents.Position := FileContents.Size; MyTest := TMyData.Create; try MyTest.Test := 'blabla'; mytest.Value:=3; MyTest.SaveToStream(FileContents); finally MyTest.Free; end; finally FileContents.Free; end; end;
function LoadStringFromStream(AStream: TStream): String; var ResultString: AnsiString; StringSize: Integer; begin Result := ''; if AStream.Size - AStream.Position < SizeOf(StringSize) then Exit; AStream.ReadBuffer(StringSize, SizeOf(StringSize)); SetLength(ResultString, StringSize); if AStream.Size - AStream.Position < StringSize then Exit; AStream.ReadBuffer(Pointer(ResultString)^, StringSize); {$ifdef UNICODE} Result := Utf8ToString(ResultString); {$else} Result := Utf8Decode(ResultString); {$endif} form1.label1.caption:='W'+result; end;
procedure TMyData.SaveToStream(AStream: TStream); var CurrentData: string; begin CurrentData := '"' + FTest + '";"' + IntToStr(FValue) + '"' + sLineBreak; AStream.WriteBuffer(PChar(CurrentData)^, Length(CurrentData) * SizeOf(Char)); end;
procedure TMyData.LoadFromStream(AStream: TStream); begin FTest := LoadStringFromStream(AStream); AStream.ReadBuffer(FValue, SizeOf(FValue)); end;
procedure TForm1.Button2Click(Sender: TObject); var FileContents:TFilestream; MyTest:TMydata; path, path_f:string; begin path := ExtractFilePath(ParamStr(0)); path_f := path + 'datei1.txt'; FileContents := TFileStream.Create(path_f, fmOpenReadWrite); MyTest := TMyData.Create;
MyTest.LoadfromStream(FileContents);
MyTest.Free;
FileContents.Free; end;
end. |
Wenn ich jetzt den Button2 drücke bekomme ich nicht ausgelesen.
|
|
jaenicke
      
Beiträge: 19311
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 14.07.11 05:50
Naja, das Laden ist da nicht so einfach. Da musst du dann immer bis zum Zeilenende lesen. Wenn du es dir einfach machen willst, nimm eine TStringList und lade damit die Datei. Dann sollte noch AssignFile, Reset, ReadLn, ... gehen, und natürlich selbst implementieren wie z.B. hier von mir:
www.delphi-forum.de/viewtopic.php?t=99933
Einen bestimmten Datensatz gezielt auslesen ist natürlich unmöglich, wenn du eine solche normale Textdatei hast.
Aber wenn es per Hand lesbar und änderbar sein soll, bleibt ja nichts weiter als ein solches Format, auch wenn es logischerweise deutlich langsamer als ein Binärformat ist. 
|
|
|