Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi String in Record Struktur (https://www.delphipraxis.net/163155-string-record-struktur.html)

zeras 17. Sep 2011 14:37

Delphi-Version: 2009

String in Record Struktur
 
Hallo

Gibt es eine Möglichkeit, einen String, der länger als 255 Zeichen ist, in einen Record zu packen und diesen dann in einer Datei zu sichern neben anderen Werten im Record (Bool, Integer etc.)?
Wenn ich Strings mit Größenangabe nutze, dann geht das, aber wenn ich nur als String definiere, wird nur der Pointer abgespeichert.
OK, ich könnte auch eine XML Datei nutzen, wollte das aber vermeiden.

Union 17. Sep 2011 14:41

AW: String in Record Struktur
 
Definiere den string doch als Array of ...

jaenicke 17. Sep 2011 14:43

AW: String in Record Struktur
 
Schreib einfach LoadFromStream und SaveToStream Methoden, dann musst du nicht mit unflexiblen Records in der Datei arbeiten:
http://www.delphi-forum.de/viewtopic...=645319#645319

himitsu 17. Sep 2011 15:27

AW: String in Record Struktur
 
ein
Delphi-Quellcode:
Array[...] of Char
und dazu einen Property als String, welcher auf diesen Array weiterleitet.

zeras 17. Sep 2011 15:42

AW: String in Record Struktur
 
Danke für die Antworten.

Werde mal sehen, welche ich umsetzen kann.

Gruß

Matthias

NickelM 17. Sep 2011 18:28

AW: String in Record Struktur
 
Im enteffekt willst du ja einen String speichern der größer 255 Zeichen ist (vllt sogar variable.
Mach doch im Record eine Integer-Variable von der Länge. und dan schreibst du den String direkt rein.
Das geht mit
Delphi-Quellcode:
 Stream.Write(String[1],Länge);
Also im record die länge des strings speichern und dann den String schreiben. Beim lesen erst record lesen und dann musst du den Speicher zum lesen in eine String-variable festlegen.

Hier eine kurze Funktion zum Prinzip.
Die länge ist halt den im record den du erst liesst.

Delphi-Quellcode:
//Schreiben
fs := TFileStream.Create(....,....);
  try
    // Erst die Länge
    fs.Write(dwLen,SizeOf(dwLen)); // Besser SizeOf als direkt 4, falls man den Typ ändert
    // Dann den eigentlichen Inhalt
    fs.Write(sBuf[1],dwLen);
  finally
    fs.Free;
  end;
  // Lesen
  fs := TFileStream.Create(....,....);
  try
    // Erst die Länge
    fs.Read(dwLen,SizeOf(dwLen));
    // Jetzt muss erst mal der Lesebuffer initialisiert werden
    sBuf := StringOfChar(#00,dwLen); // oder SetLength(sBuf,dwLen), aber dann ist der Speicher nicht initalisiert
    fs.Read(sBuf[1],dwLen);

zeras 17. Sep 2011 19:09

AW: String in Record Struktur
 
Zitat:

Zitat von NickelM (Beitrag 1125045)
Im enteffekt willst du ja einen String speichern der größer 255 Zeichen ist (vllt sogar variable.
Mach doch im Record eine Integer-Variable von der Länge. und dan schreibst du den String direkt rein.

Danke für den Tipp. Ich finde diese Lösung sehr gut, und habe schon das Speichern eingebaut.
Das Auslesen kommt morgen dran.

Sir Rufo 17. Sep 2011 19:32

AW: String in Record Struktur
 
Ist zwar leicht OT aber trotzdem :)

Ohne beurteilen zu können ob die Records für das Projekt zwingend erforderlich sind, wäre mein Vorschlag im Bezug auf das Speichern und Laden - und auch den Zugriff via GUI - auch mal über ein TClientDataSet nachzudenken, ob das nicht viel besser passen würde als das Konstrukt mit den Records.

jaenicke 18. Sep 2011 02:01

AW: String in Record Struktur
 
Zitat:

Zitat von NickelM (Beitrag 1125045)
Mach doch im Record eine Integer-Variable von der Länge. und dan schreibst du den String direkt rein.
Das geht mit
Delphi-Quellcode:
 Stream.Write(String[1],Länge);

Warum ein zusätzliches Feld im Record? Warum nicht wie ich oben unter dem Link geschrieben habe alles gekapselt?
Das halte ich für die sinnvollere Lösung.

Medium 18. Sep 2011 03:28

AW: String in Record Struktur
 
Zumal Delphi-Strings ihre Länge doch eh schon mit sich tragen - wenn wir schon bei der "ToFile()"-Record-Methode sind. Length(MyString) ist letztlich nichts anderes als "PInteger(@MyString[1]-4)^", womit der Längen-Integer implizit ohnehin schon immer vorm String steht. Und zudem via Sprachfeature "Length()" hübsch auswertbar :)

DeddyH 18. Sep 2011 09:32

AW: String in Record Struktur
 
Müsste es nicht besser "PInteger(@MyString[1]-SizeOf(Pointer))^" heißen?

Medium 18. Sep 2011 12:51

AW: String in Record Struktur
 
Es müsste Length(MyString) heissen ;) Das sollte nur demonstrieren, dass das Längenfeld tatsächlich schon da ist und von Delphi magisch mitgeführt wird, Length() also nicht erst eine Zählschleife machen muss o.ä., so dass man mit einem separaten Feld nichtmals Geschwindigkeit gewonnen hätte. Ich würde Pointerarithmetik diesertage nicht wirklich empfehlen :)

zeras 18. Sep 2011 19:24

AW: String in Record Struktur
 
Zitat:

Zitat von NickelM (Beitrag 1125045)
Im enteffekt willst du ja einen String speichern der größer 255 Zeichen ist (vllt sogar variable.
Mach doch im Record eine Integer-Variable von der Länge. und dan schreibst du den String direkt rein.
Das geht mit
Delphi-Quellcode:
 Stream.Write(String[1],Länge);
Also im record die länge des strings speichern und dann den String schreiben. Beim lesen erst record lesen und dann musst du den Speicher zum lesen in eine String-variable festlegen.

Hier eine kurze Funktion zum Prinzip.
Die länge ist halt den im record den du erst liesst.

Delphi-Quellcode:
//Schreiben
fs := TFileStream.Create(....,....);
  try
    // Erst die Länge
    fs.Write(dwLen,SizeOf(dwLen)); // Besser SizeOf als direkt 4, falls man den Typ ändert
    // Dann den eigentlichen Inhalt
    fs.Write(sBuf[1],dwLen);
  finally
    fs.Free;
  end;
  // Lesen
  fs := TFileStream.Create(....,....);
  try
    // Erst die Länge
    fs.Read(dwLen,SizeOf(dwLen));
    // Jetzt muss erst mal der Lesebuffer initialisiert werden
    sBuf := StringOfChar(#00,dwLen); // oder SetLength(sBuf,dwLen), aber dann ist der Speicher nicht initalisiert
    fs.Read(sBuf[1],dwLen);


Ich habe mich nun für deine Lösung entschieden. Das ganze habe ich noch erweitert und neben verschiedenen Werten auch noch ein Richedit Feld mit abgelegt. Das könnte ich zwar auch separat in einer Datei speichern, aber so habe ich das in einer einzigen Datei.

Die anderen Lösungen gehen bestimmt auch, aber das schien für micht das Einfachste zu sein.

Danke nochmals für die Info.

himitsu 18. Sep 2011 22:41

AW: String in Record Struktur
 
Nimm SetLength ... StringOfChar ist hier vollkommen übertrieben, denn du willst es ja gleich wieder überschreiben. :zwinker:

ABER
Wenn man man hier Read und Write verwendet, dann muß sollte man auch deren Rückgabewerte prüfen.

Oder man nutzt ReadBuffer und WriteBuffer, welche es selber Prüfen.


PS: Wozu initialisieren?
- es wird eh überschriben, womit es dann nochmals "initialisiert" wird
- wenn es nicht richtig gelesen werden konnte, dann liegt ein Fehler vor, womit die "unvollständigen" Daten eh nichts Wert sind


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz