Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TAnsiStringList - Wie (einfach) ? (https://www.delphipraxis.net/196982-tansistringlist-wie-einfach.html)

TERWI 5. Jul 2018 20:09

Delphi-Version: 2009

TAnsiStringList - Wie (einfach) ?
 
... Antworten wie "braucht doch keiner" ö. ä. werden sicher kommen !
Aber: ... ich (und sicher einige mehr) "wollen/müssen" so was "haben/brauchen".
Warum ?
Ich z.B. hab hier eine (asynchron & kontinuierliche) Datenquelle (DVB-PSI, wem das was sagt...), die mir von kilo- bis megabyte-weise Daten liefern kann, welche immer nur 8-Bit sind.
Nicht das Prob, die intern in einem (Ansi)String zu halten/speichern/laden - aber wenn sich (der Einfachheit halber) die Erforderlickeit von Text-Listen ala TStringList ergibt, ist man etwas in's Gesäß gekniffen - weil alles braucht wegen WideChar die doppelte Kapazität. Im Speicher wie auf der Platte !
Hier geht's eher um (etliche) MByte - das juckt vielleicht die HDD nicht, aber das RAM (und die CPU) !
Programm-Intern umstellen auf AnsiString ist da auch nicht so der Bringer ...

Z. Zt. behelfe ich mich damit, alle eingehenden Daten (AnsiChar) als WideChar in StringListen zu halten, diese als (ursprüngliche) AnsiChar zu speichern und umgekehrt später wieder zu WideChar zu laden.

Das funktioniert zwar so weit tadellos - auf meinem I7-Schläppi mit 16GB RAM (bisher) problemlos ... sollte aber auch aber auch auf 'kleineren Lahm-Kisten' ZEITNAH ohne Speicher-PENG in die Hufe kommen.

TStringList zu TAnsiStringList umbauen ?
Hab ich mir angesehen und versucht ... und mangels Knoff-Hoff & Zeit aufgegeben.

TAnsiStringList als (einfache) TList aus AnsiStrings wäre vielleicht "DIE" Idee ...
... aber wie den AnsiString gezielt (!) für ein "ADD" allokieren und u. a. bei "DELETE" wieder freigeben ... ohne dass es nach x-mal laden/speichern zu (nennswerten) "BummTäTäRä" mangels verfügbarem RAM kommt ???

Mega - Dank im voraus für jede Art von Erleuchtung.

Redeemer 5. Jul 2018 20:26

AW: TAnsiStringList - Wie (einfach) ?
 
Delphi-Quellcode:
type TAnsiStringList = Generics.Collections.TList<RawByteString>
?

TERWI 5. Jul 2018 20:37

AW: TAnsiStringList - Wie (einfach) ?
 
Wie soll das funktionieren ?
Ein Beispiel zu Typ- und Var-Deklaration in Verbindung mit einer Liste mit "Add" und "Delete" u. a. wäre sehr hilfreich ...

jaenicke 5. Jul 2018 20:51

AW: TAnsiStringList - Wie (einfach) ?
 
Zitat:

Zitat von TERWI (Beitrag 1406636)
TStringList zu TAnsiStringList umbauen ?
Hab ich mir angesehen und versucht ... und mangels Knoff-Hoff & Zeit aufgegeben.

Eigentlich ist da nicht viel zu tun... lediglich überall in der Klasse String durch AnsiString ersetzen.

Zitat:

Zitat von TERWI (Beitrag 1406636)
TAnsiStringList als (einfache) TList aus AnsiStrings wäre vielleicht "DIE" Idee ...

Intern nutzen sowohl TStringList als auch TList ein simples Array.

Uwe Raabe 5. Jul 2018 20:55

AW: TAnsiStringList - Wie (einfach) ?
 
Zitat:

Zitat von TERWI (Beitrag 1406636)
weil alles braucht wegen WideChar die doppelte Kapazität. Im Speicher wie auf der Platte !

Auf Platte in der Regel nicht. Wenn das Standard-Encoding aktiv ist, wird bei SaveToFile auch nur Ansi geschrieben.

TERWI 5. Jul 2018 21:41

AW: TAnsiStringList - Wie (einfach) ?
 
@ jaenicke
Zitat:

Intern nutzen sowohl TStringList als auch TList ein simples Array.
... eben genau das hatte ich auch im Sinn ...

Zitat:

Eigentlich ist da nicht viel zu tun... lediglich überall in der Klasse String durch AnsiString ersetzen.
... dito - und alles von TStringList aus Classes in eine eigene Unit kopiert und dann dass "anpassen" versucht ...
... habs wie gesagt (erst mal) aufgegeben. Das übersteigt leider meinen Delphi-Internen Horizont.
... da sind offensichtlich noch etliche andere Klassen im Spiel, die nicht mal eben so on the fly to go zu ändern sind :)

@ Uwe
Zitat:

Auf Platte in der Regel nicht. Wenn das Standard-Encoding aktiv ist, wird bei SaveToFile auch nur Ansi geschrieben
... ich hab hier nix betreff "Standard Encoding" geändert/eingestellt. (Wie geht/funktioniert das ?)
Ohne mein spezielles "Umdängeln" wird mit widechar auf die Platte geschrieben.
Ich verwende hier TFileStream zu speichern und laden, was m.M.n. betreff der String-Typen aber keine Rolle spielen sollte. Mit Block-Read/Write hatte ich vor Jahren schon ähnliche Probs.

Ooops - zur Info:
Ich verwende hier nicht irgendwelche Speicher-/Lade-Funktionen der TStringList !
Die TSL's sind in meiner App Teile von eigenen Records und müssen aus/in eigenem "Daten-Bestand" eben "händisch" verarbeitet werden.

KodeZwerg 5. Jul 2018 22:33

AW: TAnsiStringList - Wie (einfach) ?
 
Wenn eh Records verwendet werden dann definiere doch gleich ein Hauptrecord von dem sich Dein Inhalt abbildet.
Delphi-Quellcode:
type
  TKrams = record
    EinInteger: Integer;
    EinString: String;
    EinAnsiString: AnsiString;
  end;

var
  Krams: Array of TKrams; // das zum füllen nutzen
  KramsDatei: File of TKrams; // das fürs Dateihandling falls Du laden & speichern möchtest

mit Read()/Write() Lesen/Schreiben und selber Funktionen schreiben die das Record verwalten.
Das könnte man so mit kleinen Index-Mengen realisieren.

mkinzler 6. Jul 2018 07:18

AW: TAnsiStringList - Wie (einfach) ?
 
Zitat:

type TAnsiStringList = Generics.Collections.TList<RawByteString> ?
Zitat:

Zitat von TERWI (Beitrag 1406639)
Wie soll das funktionieren ?
Ein Beispiel zu Typ- und Var-Deklaration in Verbindung mit einer Liste mit "Add" und "Delete" u. a. wäre sehr hilfreich ...

Mal ausprobiert?
Delphi-Quellcode:
var
  MyAnsiStringList: TAnsiStringList;
...
    MyAnsiStringList := TAnsiStringList.Create;
    MyAnsiStringList.Add( 'Hallo');
    MyAnsiStringList.Add( 'Welt');

TiGü 6. Jul 2018 08:09

AW: TAnsiStringList - Wie (einfach) ?
 
Kannst du mal ein bisschen Quelltext zur Verwendung deiner bisherigen Lösung zeigen?
Wenn ich mir den Wiki-Artikel so anschaue (https://de.wikipedia.org/wiki/DVB-SI), würde ich eher ein TDictionary<DeinSchlüssel, DeineDaten> verwenden, welches auch schon in Delphi 2009 vorhanden ist.

DeineDaten können hier TBytes (array of Bytes) sein und/oder ein Record, welches automatisch per impliziter/expliziter Methoden die Raw-Daten lesen, umwandeln und wieder ausgeben kann.

Wie bekommst du denn die Daten? Eine externe TCP/Http-Quelle? Liest du hier als String? Eine Verwendung direkt als Bytes/Stream wäre vorteilhafter.

freimatz 6. Jul 2018 09:39

AW: TAnsiStringList - Wie (einfach) ?
 
Kathinka ist mal wieder fleißig :wink: - SCNR

TERWI 6. Jul 2018 10:15

AW: TAnsiStringList - Wie (einfach) ?
 
Das mit
type TAnsiStringList = Generics.Collections.TList<RawByteString> ?
hab ich immer noch nicht verstanden ...

Die Daten ziehe ich direkt aus dem Transportstrom, zerlege sie dann in (DVB-) System-, Netzwerk-, Service- und EPG(EIT)-Daten.
Hier geht es im besondern um die EIT mit jeweils (reichlich) Text zu "Events" für 'jetzt, später, demnächst' (max. 14 Tage).
Eine komplette 'Sammlung' von ca. 500 Programmen wird da schon recht umfangreich ... Wenn man vorhandenen Teletext dazu auch noch sammelt, wirds noch dicker.

Ein (Short-)Event besteht aus aus 2 Strings mit je max. 256 Zeichen 8-Bit.
Ein (Extended-)Event hate eine Item-Liste aus 2 Strings wie Short. Die Eintäge können sowohl als auch sein - ebenso kann die Liste 0 sein oder auch ellenlang. Deswegen hier (der Einfachheit halber) eine TStringList.
Dazu gibt es noch einen String aus AnsiChar, dessen Länge theoretisch nicht begrenzt ist, prinzipiell aber aus einer Anzahl x-Strings mit max. 256 Zeichen besteht.

Die 3 AnsiStrings mit der TStringList und ner Latte weiterer Daten stecken in einem Record.

Im Moment handle ich das mittels casting so:
Delphi-Quellcode:
...
  // write EE_item-List as ansistring !
  n := EVRec.EE_item.Count;
  EVfsw.Write(n, 2);                     // write count of EE_item
  for ii := 1 to EVRec.EE_item.Count do  // loop items (if any)
  begin
    sansi := ansistring(EVRec.EE_item[i-1]);
    EVfsw.Write(i, 2);                   // write number of item
    n := Length(sansi);
    EVfsw.Write(n, 2);                   // write length of EE_item
    if (n > 0) then
    EVfsw.Write(sansi[1], n);          // write EE_item
  end;
...
Und wieder zurück:
Delphi-Quellcode:
...
  // read EE_item-List as ansistring !
  inc(sizeread, EVfsr.Read(n, 2));        // read count of EE_item
  for ii := 1 to n do         // loop items (if any)
  begin
    inc(sizeread, EVfsr.Read(nn, 2));        // read number of item
    // ... check if nn = ii !
    inc(sizeread, EVfsr.Read(nn, 2));        // read length of EE_item
    SetLength(sansi, nn);
    if (nn > 0) then                         // read EE_item
    begin
      inc(sizeread, EVfsr.Read(sansi[1], nn));
      EVrec.EE_item.Add(sansi);
    end;
  end;
...
EVfsr und EVfsw sind TFileStreams.
EVRec.EE_item ist die TStringListe.

Neutral General 6. Jul 2018 10:19

AW: TAnsiStringList - Wie (einfach) ?
 
Was gibts da nicht zu verstehen?
Deklarier halt EVRec.EE_item als TList<RawByteString> (oder AnsiString?) und fertig.

TERWI 6. Jul 2018 10:32

AW: TAnsiStringList - Wie (einfach) ?
 
Wenn ich das so mache
Delphi-Quellcode:
TAnsiStringList = TList<RawByteString>;
bekomme ich diese Meldung:
Zitat:

[DCC Fehler] DVB_PSI_Data.pas(101): E2003 Undeklarierter Bezeichner: 'TList<>'

Neutral General 6. Jul 2018 10:39

AW: TAnsiStringList - Wie (einfach) ?
 
Deswegen hatte Redeemer z.B. Generics.Collections.TList<RawByteString> geschrieben was implizieren soll, dass man die Unit "Generics.Collections" einbinden muss.

mkinzler 6. Jul 2018 10:39

AW: TAnsiStringList - Wie (einfach) ?
 
Zitat:

Zitat von TERWI (Beitrag 1406679)
Wenn ich das so mache
Delphi-Quellcode:
TAnsiStringList = TList<RawByteString>;
bekomme ich diese Meldung:
Zitat:

[DCC Fehler] DVB_PSI_Data.pas(101): E2003 Undeklarierter Bezeichner: 'TList<>'

Die hohe Kunst des Copy and Paste

Delphi-Quellcode:
TAnsiStringList = Generics.Collections.TList<RawByteString>;
Es muss natürlich noch die Unit Generics.Collections eingebunden werden.

TERWI 6. Jul 2018 10:48

AW: TAnsiStringList - Wie (einfach) ?
 
Arrrrgh .... peinlich. :oops:
Abgeändert und kompiliert.
Test wird etwas länger dauern.

Redeemer 6. Jul 2018 12:01

AW: TAnsiStringList - Wie (einfach) ?
 
Zitat:

Zitat von Neutral General (Beitrag 1406678)
Was gibts da nicht zu verstehen?
Deklarier halt EVRec.EE_item als TList<RawByteString> (oder AnsiString?) und fertig.

RawByteString (eigentlich auch nur ein spezieller AnsiString) ist hier denke ich besser, da da garantiert nicht sinnlos herumkonvertiert wird.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:36 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