Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - alternative für TStringlist gesucht


ALF - Sa 29.01.11 13:07
Titel: alternative für TStringlist gesucht
Ich hab mir mit meiner Idee alles in Stringlisten abzulegen und zu speichen selbst ein Bein gestellt :oops:
Die Idee war am Anfang noch gut (2-3 Parameter mit abzuspeichern) und die wieder mit einzulesen. Mittlerweile sind es 12 und ich befürchte es werden evtl noch 2-3 mehr.

Mal ein kleines Beispiel: die Trennung erfolgt mit ';' die Parameter sind, String, Integer, Real.

Quelltext
1:
 Name='"dies ist ein Kommentar"; 10; 2,3; 0,8; 123; 456; 0; 222; 234; 2'                    

Das einlesen erfolgt dann in einem packed of Record.
Beim erstellen der Komponenten, (in Abhängigkeit wieviele Einträge es in der Stringliste gibt) muss ich einzelne Parameter schon berücksichtigen. Zur Laufzeit können alle Parameter geändert werden (echtzeit) und müssen gleich in die Stringliste übernommen. Zum Schluss auch wieder gespeichert!

Da die "Parameter" ja nur als String vorliegen, könnt ihr euch vorstellen wie umständlich das ist, auf einzelne zuzugreifen. String auseinanderlesen in ein Record packen, einzelenen Parameter anzeigen/ändern und den Record wieder in ein String legen um ihn in der Stringliste wieder einzufügen.

Was ich also suche ist ne Alternative für das ganze, so richtig gefunden hab ich da nichts.
Vielleicht habt ihr ne Idee?

Gruss Alf


delfiphan - Sa 29.01.11 13:10

Schreibe eine Klasse oder Record und einen separaten Mechanismus für die Serialisierung und Deserialisierung. (Der Hintergedanke/Sinn deiner StringList habe ich nicht verstanden, bzw. hast du nicht erklärt)

Für die Serialisierung/Deserialisierung ist XML ideal: Die Spezifikationen sind erweiterbar, du kannst Validierung haben (XML Schema), verschiedene Typen haben, und es handelt sich um einen Standard. Du musst den Parser auch nicht selbst schreiben.

PS: Wenn du dir dein Leben vereinfachen willst: .NET bietet da Standardmechanismen, Klassen und Patterns für all die Sachen. In Delphi musst du dir das halt irgendwie zusammenreimen.


jaenicke - Sa 29.01.11 13:26

Nicht nur .NET hat dafür Funktionalitäten. ;-) In Delphi kann man auch sehr einfach Klassen serialisieren. Nämlich in das delphieigene DFM Format. Das funktioniert auch sehr gut.
Hier gibts in der Doku ein entsprechendes Beispiel:
http://docwiki.embarcadero.com/CodeExamples/en/ComponentToString_(Delphi)

Das geht natürlich genauso mit eigenen Klassen, wenn die entsprechenden Eigenschaften unter published stehen.


ALF - Sa 29.01.11 13:26

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
(Der Hintergedanke/Sinn deiner StringList habe ich nicht verstanden, bzw. hast du nicht erklärt)

Bevor ich jetzt gross schreibe was der Hintergedanke ist, hier ein kleiner Auszug aus einer von möglich 8 Listen

Quelltext
1:
2:
3:
4:
5:
6:
G:\Musik\PLAYER1\01 Dschu S 4.wav="";10;0;0;0;0;0;0;0;1
G:\Musik\PLAYER1\02_Tiger_S6.wav="er geht zu Mogli";10;0;0;0;0;0;0;0;1
G:\Musik\PLAYER1\03_Bum Bum_S11.wav=" Mogli allein, mit Lw";10;0;0;0;0;0;0;0;1
G:\Musik\PLAYER1\04_Elef_S12.wav="";10;0;0;0;0;0;0;0;1
G:\Musik\PLAYER1\05_Elef2_S13.wav="";10;0;0;0;0;0;0;0;1
G:\Musik\PLAYER1\05b_rickauf_S13.wav="auf Sicht";10;0;0;0;0;0;0;0;1


Das mit xml hab ich mir auch schon angeschaut, bin mir aber nicht sicher ob das zum schluss genauso kompliziert wird. Selbst an ini hab ich schon gedacht.

Gruss Alf


jaenicke - Sa 29.01.11 13:37

Wie gesagt: Wenn du das in eine Klasse packst, kannst du das mit dem fertigen Code aus dem Link einfach speichern ohne selbst etwas zu machen.
Und wenn du eine TCollection-Klasse damit erstellst, kannst du auch eine Sammlung mehrerer solcher Klassen einfach so speichern ohne weiteren eigenen Code.


bummi - Sa 29.01.11 13:40

Du könntest die einzelnen String einer Stringlist zuweisen und dort den Delimiter auf ";" einstellen um auf die Elemente per Index zuzugreifen...
Oder das ganze in eine INI-Struktur bringen, oder, oder...


delfiphan - Sa 29.01.11 13:49

DFM ist ein valider Punkt :zustimm:
Schade, dass das ganze so auf TComponent abzielt und kein generisches Konzept gibt. Naja, wurde ja auch für GUI-Forms entwickelt. .NET geht da natürlich einiges weiter und ist einiges komfortabler.


jaenicke - Sa 29.01.11 14:07

Du brauchst kein TComponent. TPersistent reicht bereits. ;-)


delfiphan - Sa 29.01.11 14:16

Die Methode im Link und TStream.ReadComponent/TStream.WriteComponent wollen ein TComponent. TPersistent macht einfach {$M+} aber das alleine ist erst die halbe Miete.


ALF - Sa 29.01.11 14:27

@bummi: bringt ja auch nix, da ich ja (valuefromindex) nur als String habe und ich diesen String ja erst auseinander nehmen muss um ihn wieder in einer anderen StringListe zu laden. Das hatte ich mir auch schon überlegt, so würde ich mir Record sparen aber leider auch nicht effektiver als meine jetztige.

@jaenicke: So richtig schnall ich das nicht, wie ich dies bei mir einsetzten kann! :gruebel:

Gruss Alf


bummi - Sa 29.01.11 15:17

die anhängende Datei passt nicht ganz für Deine Anforderung, aber gegf. kannst Du Dir die benötigte ArrayOfRecord - Funktion zusammenkopieren....


ALF - Sa 29.01.11 16:18

@bummi:
ähm... Ein Array of Variant währe evtl einfacher? Aber irgend wann muss ich ja speichern/laden! Und als was Speichere ich das?, wenn nicht als Liste(TStringlist)? Egal was ich für die zusätzlichen Parameter nehme Array/Record. Ausschlag gebend ist das abspeichern/laden und daraus resultiert das einlesen, was ja der eigentliche Aufwand bedeutet! Oder hab ich Dein Beispiel missverstanden :gruebel:

Zumal das ganze noch dynamisch sein muss!

Darum bin ich ja auf TStringList hängengeblieben weil dies am einfachsten ist(ausser, wenn es nun um die vielen parameter geht, die nach und nach dazugekommen sind)!

@jaenicke: Vorschlag liest sich gut! Aber wie schon erwähnt mh... wie umsetzen, absolutes Neuland!

Gruss Alf


bummi - Sa 29.01.11 19:45

@ALF
Das Array kann Dynamisch sein, der Record wird ja wohl fix sein? (1 String, 9*Integer)?
Ein Save2_MyteRec_Array, Load2_MyteRec_Array müsstest Du dann relativ zügig anhand des Beispiels basteln können.


jaenicke - Sa 29.01.11 20:13

user profile icondelfiphan hat folgendes geschrieben Zum zitierten Posting springen:
Die Methode im Link und TStream.ReadComponent/TStream.WriteComponent wollen ein TComponent. TPersistent macht einfach {$M+} aber das alleine ist erst die halbe Miete.
Gut, da hast du Recht. Man kann aber TReader und TWriter selbst erzeugen (auch wenn die Hilfe sagt, dass man das nicht sollte, aber mehr macht ReadComponent und so auch nicht). Und dort gibt es z.B. ein ReadCollection, das mit einer Collection von TPersistent-Nachfahren funktioniert. Aber du hast schon Recht, nach außen hin ist nur TComponent wirklich gut erreichbar.

user profile iconALF hat folgendes geschrieben Zum zitierten Posting springen:
@jaenicke: Vorschlag liest sich gut! Aber wie schon erwähnt mh... wie umsetzen, absolutes Neuland!
Zu Collections findest du hier etwas:
http://delphi.about.com/library/bluc/text/uc083101d.htm

Im Grunde als Grundgerüst:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
type
  TMyClass = class(TComponent)
  private
    FMyValue: string;
    procedure SetMyValue(const Value: string);
  published
    property MyValue: string read FMyValue write SetMyValue;
  end;
Und das Objekt, dass du dann von der Klasse erstellst, kannst du dann an die verlinkten Funktionen füttern.


ALF - So 30.01.11 12:53

Jo, nach ewigem durchlesen schein ich es erst mal 'Theoretisch' zu verstehen!?
Da ich mir für sowas immmer erst ne so genannte Demo machen muss, um es dann auch praktisch zu verstehen, schieb ich es erst mal nach hinten, (Bei mir dauert sowas, auch aus Zeitgründen, ewig) zumal, wenn ich es dann verstanden habe, ich ja auch mein jetztiges komplett neu machen müsste. Da ich aber fast fertig bin, muss ich es erst mal so lassen.

Wenn ich dieses jetztige neu aufsetze, bin irgendwie nicht ganz zufrieden damit, werd ich dies berücksichtigen.

Darum Danke ich euch beiden

Gruss Alf

PS: es ist natürlich auch das unbekannte, was mich zurück hält. Bin nur ein langsam Denker


delfiphan - So 30.01.11 18:52

Ich will dich ja nicht abwerben, aber da das auch ein C#-Forum ist, hier zum Vergleich. Wenn du mich fragst, musst du da viel weniger denken, und kannst viel weniger falsch machen. In .NET schreibst du deine Klasse mit paar Properties:

C#-Quelltext
1:
2:
3:
4:
5:
6:
public class Data
{
    public string Path { get; set; }
    public string Title { get; set; }
    public int Number { get; set; }
}

füllt sie mit paar Daten

C#-Quelltext
1:
2:
3:
4:
5:
6:
var dataList = new List<Data>
    {
        new Data { Number = 1, Path = @"C:\path1", Title = "Abc" },
        new Data { Number = 2, Path = @"C:\path2", Title = "Abc" },
        new Data { Number = 3, Path = @"C:\path3", Title = "Abc" }
    };

und schreibst das in ein XML. Fertig.

C#-Quelltext
1:
2:
3:
4:
5:
using (var writer = new StreamWriter(@"C:\irgendwo\daten.xml"))
{
    var serializer = new XmlSerializer(typeof(List<Data>));
    serializer.Serialize(writer, dataList);
}


In Delphi musst du dich entscheiden, ob du eine (nicht-generische!) TCollection für Serialisierung verwenden willst, eine eigene Klasse mit eigener Serialisierung haben willst, oder doch ein Memory DataSet wenn du es mal in einem Grid darstellen willst. Je nach dem hast du dann Vor- und Nachteile. Du schreibst je nach dem eigene Schleifen, Sortierfunktionen, eigene Serialisierungsunits, und. und. und..
In C# ist alles viel einheitlicher. Du willst eine neue Liste mit den Daten wo "Number > 2" und nach "Path" sortiert? Ganz einfach: var dataGreater2 = dataList.Where(item => item.Number > 2).OrderBy(item => item.Path);. Du willst es in einem Grid anzeigen? Ganz einfach, du weist es (ggf. über Binding) einer DataGrid zu. Du willst ein XML draus machen? Nimm ein XmlSerializer. Du willst gewisse Properties doch nicht im XML haben? Alles über Attribute In-Code konfigurierbar.
Du willst die Daten mal über einen (z.B. Soap) Service zugreifbar machen? Mal über TCP, HTTP oder doch lieber Named Pipes oder meinetwegen über alle Schnittstellen parallel? Alles in wenigen Minuten gemacht.

Wieso Stunden verbraten, wenn's in Minuten geht? Ich meine du sprichst von Demo, d.h. es ist ein neues Projekt?


ALF - So 30.01.11 20:36

Ne, aber ich hab mit den Beispielen von @jaenicke und @bummi noch nichts gemacht!
Und sowas, in ein fast fertigem Projekt einzubinden ohne die geringste Ahnung zu haben, was ich da wie wo machen muss, neeee. Dazu fehlen, meiner seits, einfach Erfahrung und die Grundlagen!

Auf gut deutsch, ich fange immer wieder bei einem Projekt bei null an.
Mach dies ja nur alle Jahre mal :wink:

Ich hab es zwar verstanden, aber Verstehen und Umsetzten, mhhhhh....
Da mach ich mir lieber erst ein kleines Beispiel/Demo und wenn ich das kapiert habe, kann ich es auch nutzen in ein grösseres Projekt :wink:

Gruss Alf


Horst_H - So 30.01.11 21:14

Hallo,
wäre nicht eine CSV-Datenbank etwas passendes?
http://www.jansfreeware.com/jfdelphi.htm dort jvcsvbase
Auch xml etc ist dort zu finden

Gruß Horst