Autor Beitrag
Furious_Dragon
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Fr 04.09.09 16:13 
Hallo,

Also ich Programmiere mit Delphi 7 und würde gerne eine Memobox über einen Stream in eine typisierte Datei schreiben/auslesen aber stell mich da im Moment ein bisschen Blöd an bis jetzt hab ich mit Streams immer ganz gut arbeiten können wenn ich wusste das z.B. Strings keine bestimmte Größe überschreiten können jetzt muss dieser String aber auch über 255 Zeichen groß werden können und da stellt sich mir die Frage wie ich das am besten erledigen kann.

Bin für jeden Vorschlag offen und beantworte gerne jede Frage die ich hiermit aufgeworfen habe ;o)

Danke schonmal für die Hilfe!
Olli

Moderiert von user profile iconNarses: 2. Frage entfernt.
Moderiert von user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Fr 04.09.2009 um 16:20


Zuletzt bearbeitet von Furious_Dragon am Fr 04.09.09 16:31, insgesamt 1-mal bearbeitet
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Fr 04.09.09 16:18 
Moin und :welcome: im Forum!

user profile iconFurious_Dragon hat folgendes geschrieben Zum zitierten Posting springen:
Also ich Programmiere mit Delphi 7 und würde gerne eine Memobox über einen Stream in eine typisierte Datei schreiben/auslesen aber stell mich da im Moment ein bisschen Blöd an bis jetzt hab ich mit Streams immer ganz gut arbeiten können wenn ich wusste das z.B. Strings keine bestimmte Größe überschreiten können jetzt muss dieser String aber auch über 255 Zeichen groß werden können und da stellt sich mir die Frage wie ich das am besten erledigen kann.
Um es kurz zu machen: mit typisierten Dateien gar nicht. :nixweiss:

Nimm z.B. einen Suche in: Delphi-Forum, Delphi-Library TFILESTREAM. :idea:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Furious_Dragon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Fr 04.09.09 16:30 
Hey

... das ging schnell ;)

Ich sitz einfach schon zulange vor dem Code ;)

Also ich nutze natürlich schon ein TStream - aber wie? Steh da im Moment ein wenig ratlos vor und je mehr ich im Internet finde umso verwirrter werde ich

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
var
  Stream: TFileStream;
  str : ? //<- Muss über 255 Zeichen aufnehmen können (funktioniert also mit string nichtmehr) hilft
          // mir das AnsiString - kann ich den in eine Datei schreiben?
begin
  Stream := TFileStream.(filename, fmCreate);
  Stream.Write(str, sizeof(str));
end;


So wirds ja nicht funktionieren bzw hats bei mir nicht nur solange als Typ string[255] da steht.
Sprint
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 849



BeitragVerfasst: Fr 04.09.09 16:50 
Wenn nicht anders eingestellt, dann ist in deiner Delphi Version ein string schon ein AnsiString.
Über Lines.SaveToFile / SaveToStream kannst du den Text einer TMemo auch speichern.

_________________
Ciao, Sprint.
Furious_Dragon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Sa 05.09.09 10:43 
Hi

also hab das mal mit Memo und SaveToStream ausprobiert nur leider bekomme ich eine Zugriffsverletzung


e ist ein Record
und Frage ist von TStrings (wird anschließend in die Memobox geschrieben)

ausblenden Delphi-Quelltext
1:
e.Frage.LoadFromStream(Stream);					


und dann habe ich ausprobiert ob es funktioniert wenn ich vorher ein TStrings erzeuge -> hatte aber leider ein Abstract Error zur folge... kann doch eigentlich nicht so schwer sein ;)
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 05.09.09 10:47 
Schau dir einmal die Hilfe zu TStrings an... :roll:
Zitat:
TStrings contains abstract or, in C++ terminology, pure virtual methods and should not be directly instantiated.
Wie wäre es mit TStringList z.B.?
Aber insgesamt wäre eine Klasse mit Methoden zum Laden und Speichern vermutlich statt des Records sinnvoller.
ub60
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 764
Erhaltene Danke: 127



BeitragVerfasst: Sa 05.09.09 11:00 
Speichern eines beliebigen Strings:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var s : String;
    Stream : TFileStream;
    Laenge : Integer;
begin
  Stream:=TFileStream.Create('string.dat',fmCreate);
  s:='Das ist mein String';
  Laenge:=Length(s);
  Stream.Write(Laenge,SizeOf(Laenge));  // Länge des Strings
  Stream.Write(s[1],Laenge);            // Das [1] ist wichtig! Bei s steht nämlich nur der Zeiger auf den String.
  Stream.Free;
end;

Einlesen dieses Strings:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
var s : String[20];
    Laenge : Integer;
    Stream : TFileStream;
begin
  Stream:=TFileStream.Create('string.dat',fmOpenRead);
  Stream.Read(Laenge,SizeOf(Laenge));   // Länge lesen
  SetLength(s,Laenge);                  // String auf diese Länge vorbereiten
  Stream.Read(s[1],Laenge);
  ShowMessage(s);
  Stream.Free;
end;


ub60
Furious_Dragon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Sa 05.09.09 11:00 
:roll: Na toll und das mir... (Bin sonst nur am Java Programmieren und da sollte ich es eigentlich kennen ;) )
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Sa 05.09.09 11:11 
user profile iconub60 hat folgendes geschrieben Zum zitierten Posting springen:
Speichern eines beliebigen Strings: [...]
Wobei das so nicht in allen Delphiversionen klappt, ab Delphi 2009 geht das so nicht mehr.
Entweder man berechnet dort die Größe von 2 Byte, also SizeOf(Char) ein, wenn man die Daten liest und schreibt, oder man benutzt UTF-8. Wobei mit UTF-8 dann auch ein Austausch von Daten von Delphi 2009 Programmen mit solchen von älteren Versionen usw. möglich ist. Dazu hier ein Auszug aus einem meiner Programme (wenig getestet mit D2009 bisher, sollte aber gehen):
ausblenden 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:
function TAppConfigManager.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} // ab Delphi 2009
  Result := Utf8ToString(ResultString);
  {$else}
  Result := Utf8Decode(ResultString);
  {$endif}
end;

procedure TAppConfigManager.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;
// EDIT:
Für echte Unicodeunterstützung unter Delphi 2009 und 2010 ist natürlich der Weg via SizeOf(Char) besser.
Furious_Dragon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: Sa 05.09.09 22:51 
Hey danke!!!

Bin nach 6h schlaf auch wieder besser auf meinen Code zu sprechen und es hat mit dem Code von Ub60 super funktioniert! Danke auch an jaenicke hätte bestimmt auch damit funktioniert aber da ich mit Delphi 7 arbeite und durch den Code den du gepostet hast nur zur hälfte durchgestiegen bin hab ich den von Ub60 bevorzugt ;) Macht das Fehler finden einfacher wenn man versteht was da steht ;)

und danke nochmal für die schnellen Antworten! Hab gleich die nächste Frage aber dafür gibts ein neuen Thread!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 06.09.09 04:41 
Wichtig ist bei dem Quelltext dann noch, dass du noch ein try..finally hinzufügst, denn das fehlt in dem oben geposteten Quelltext. So hast du dann ggf. ein Speicherleck, wenn da eine Exception auftritt. Außerdem musst du noch die Pfadangabe hinzufügen, falls du das nicht schon getan hast, denn ohne funktioniert es nur rein zufällig. Also so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
var
  s: String;
  Stream: TFileStream;
  Laenge: Integer;
begin
  Stream := TFileStream.Create(ExtractFilePath(ParamStr(0)) + 'string.dat', fmCreate);
  try
    s := 'Das ist mein String';
    Laenge := Length(s);
    Stream.Write(Laenge, SizeOf(Laenge));  // Länge des Strings
    Stream.Write(s[1], Laenge);            // Das [1] ist wichtig! Bei s steht nämlich nur der Zeiger auf den String.
  finally
    Stream.Free;
  end;
end;
Und umgekehrt analog.
HelgeLange
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: So 06.09.09 16:36 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconub60 hat folgendes geschrieben Zum zitierten Posting springen:
Speichern eines beliebigen Strings: [...]
Wobei das so nicht in allen Delphiversionen klappt, ab Delphi 2009 geht das so nicht mehr.
Entweder man berechnet dort die Größe von 2 Byte, also SizeOf(Char) ein, wenn man die Daten liest und schreibt, oder man benutzt UTF-8. Wobei mit UTF-8 dann auch ein Austausch von Daten von Delphi 2009 Programmen mit solchen von älteren Versionen usw. möglich ist. Dazu hier ein Auszug aus einem meiner Programme (wenig getestet mit D2009 bisher, sollte aber gehen):


EinFrage : Kann man denn einen Delphi 2009 string (also unicode) in UTF8 encoded String speichern und zu 100% wiederherstellen als AnsiString ?

Wenn nicht, reicht doch ein typecast, weil Delphi das ab 2009 handelt. Sagen die selbst im Embarcadero Forum.

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 06.09.09 16:43 
Ich habe es noch nicht ausreichend testen können. Aber wenn ich den Unicode-String UTF-8 encode in einen AnsiString, dann sollte der danach doch auch wieder in einen echten Unicode-String decodiert werden können. :gruebel:

Das funktioniert in Webseiten doch auch.
Furious_Dragon Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 16



BeitragVerfasst: So 06.09.09 17:21 
Hey danke für den Hinweis. Hab ich aber schon dran gedacht gehabt und selber eingebaut Delphi ist bei mir nur schon verdammt lange her und durch andere Programmiersprachen die danach kamen ein wenig in Vergessenheit geraten ;)

und das mit dem Pfad hab ich eh durch Open/SaveDialog aber danke nochmal sonst wär ich an der Stelle bestimmt auch irgendwann hängen geblieben ;)
HelgeLange
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 735
Erhaltene Danke: 6

Windows 7
Delphi7 - Delphi XE
BeitragVerfasst: So 06.09.09 17:50 
user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Ich habe es noch nicht ausreichend testen können. Aber wenn ich den Unicode-String UTF-8 encode in einen AnsiString, dann sollte der danach doch auch wieder in einen echten Unicode-String decodiert werden können. :gruebel:

Das funktioniert in Webseiten doch auch.


In meinem Projekt bin ich einen anderen Weg gegangen, ich speicher einfach ein zusätzliches Byte mit weg, wo ich danach weiss, ob ich einen UnicodeString oder AnsiString gespeichert hatte. Das erlaubt mir, auch mit einer Pre-2009 Delphi version meine Streams zu lesen, die mit 2009 oder 2010 geschrieben wurden.
Klar, es gibt eine Stelle, wo es hakt. Wenn man einen Unicode-String hat mit chinesischen Zeichen drin und man will das mit einer Nicht-Unicode-Version von Delphi lesen, dann wird das natürlich auch in einen AnsiString verwandelt und dabei kommt es zu Verlusten :( Aber das ist die einzige Stelle und das stört mich nicht, meine Chinesisch-Kenntnisse sind limitiert :D

_________________
"Ich bin bekannt für meine Ironie. Aber auf den Gedanken, im Hafen von New York eine Freiheitsstatue zu errichten, wäre selbst ich nicht gekommen." - George Bernhard Shaw