Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   StringHelper Methode Split fehlerhaft? (https://www.delphipraxis.net/189498-stringhelper-methode-split-fehlerhaft.html)

Kostas 19. Jun 2016 13:22

StringHelper Methode Split fehlerhaft?
 
Hallo Zusammen,

hat jemand eine Erklärung dafür warum die Split Methode ein ArrayItem weniger hat wenn das letzte Element leer ist?
Wenn ich Feld1-Feld4 jeweils mit einem String befülle und die Länge abfrage bekomme den richtigen Wert Length(splited) = 4.
Ist das letzte Feld4 jedoch leer, ist Length(splited) = 3. Das kann doch nicht sein oder?

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
var s:string;
    splited:TArray<String>;
    Feld1,Feld2,Feld3,Feld4:string;
begin
  Feld1 := 'F1';
  Feld2 := 'F2';
  Feld3 := 'F3';
  Feld4 := 'F4';
//  Feld4 := '';

  s := s.Join(',',[Feld1,Feld2,Feld3,Feld4]);
  splited := s.Split([',']);
  ShowMessage(Length(splited).ToString());
end;
Gruß Kostas

Whookie 19. Jun 2016 15:22

AW: StringHelper Methode Split fehlerhaft?
 
Sieht so aus als wäre das wirklich ein Problem in TStringHelper.IndexOfAny() bzw. TStringHelper.InternalSplit zu sein und gehört wohl ins QC.

Ein Workaround für dich wäre momentan

Delphi-Quellcode:
  s := s.Join(',',[Feld1,Feld2,Feld3,Feld4])+',';


das muss natürlich entfernt werden wenn es einen fix gibt.

Sir Rufo 19. Jun 2016 15:36

AW: StringHelper Methode Split fehlerhaft?
 
Was sagt denn die Doku?

Da scheint wohl per Default
Delphi-Quellcode:
TStringSlitOptions.ExcludeEmpty
gesetzt zu sein. Aber es gibt ja ein overload wo man diese Option mit
Delphi-Quellcode:
TStringSlitOptions.None
übergeben kann.

Kostas 19. Jun 2016 15:57

AW: StringHelper Methode Split fehlerhaft?
 
Hallo Sir Rufo,

habe ich ausprobiert. bei None (default) kommt genau das raus wie bei mir.
Bei ExcludeEmpty werden alle leeren Felder entfernt. Das ist noch viel schlimmer da sich die Anzahl der Felder permanent ändern würde.



Gruß Kostas

Kostas 19. Jun 2016 16:02

AW: StringHelper Methode Split fehlerhaft?
 
Hallo Whookie,

das ist keine Option wie ich finde. Ich schreibe ein csv File raus welches Fremdsystem lesen sollen. Ich kann also nicht einfach ein weiteres Feld hinzufügen um nur das letzt Feld zu exportieren.
Kann es wirklich sein dass es ein Bug ist?

Und noch eins:
Eigentlich hätte ich erwartet wenn ich beim Split die Start- und Ende Quote angebe, dass beim Spliten die Quote nicht dabei sind oder zumindest Einstellbar ist. Das ist nicht der Fall, sie werden immer exportiert.
Delphi-Quellcode:
Splited := r.Split([','],'"','"');
Gruß Kostas

Kostas 19. Jun 2016 16:26

AW: StringHelper Methode Split fehlerhaft?
 
Hallo Zusammen,
es kommt noch schlimmer:

ich habe in einem Feldinhalt das: (§§") also Quote ich das Feld zu "(§§")"
Split erkennt das nicht sauber wenn ich Start und Ende Quote char angebe.

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
var s,n:string;
    splited:TArray<String>;
    Feld1,Feld2,Feld3,Feld4:string;
begin
  Feld1 := 'F1';
  Feld2 := 'F2';
  Feld3 := '"(§§")"';
  Feld4 := 'F4';

  s := s.Join(',',[Feld1,Feld2,Feld3,Feld4]);
  splited := s.Split([','],'"','"');

  for n in splited do
  begin
    meDSBZMIVerein.Lines.Add(n);
  end;

//  ShowMessage(Length(splited).ToString());
end;
Das Ergebnis
F1
F2
"(§§")",F4

Also nur drei items!


Gruß Kostas

Sir Rufo 19. Jun 2016 16:34

AW: StringHelper Methode Split fehlerhaft?
 
Für das was du da machen möchtest ist
Delphi-Quellcode:
String.Split
in keinster Weise die richtige Wahl. Damit wird ein String stumpf an den Delimitern getrennt. Das ist die Aufgabe von dieser Methode.

Was du suchst ist das, was
Delphi-Quellcode:
TStringList
kann, indem du den
Delphi-Quellcode:
DelimitedText
zuweist. Es gibt noch die ein oder andere Eigenschaft, mit der du das Verhalten beeinflussen kannst (QuoteChar, Delimiter, StrictDelimiter).

Hier wird dann auch die Struktur berücksichtigt (das was du suchst).

Kostas 19. Jun 2016 16:46

AW: StringHelper Methode Split fehlerhaft?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1340554)
Für das was du da machen möchtest ist
Delphi-Quellcode:
String.Split
in keinster Weise die richtige Wahl. Damit wird ein String stumpf an den Delimitern getrennt. Das ist die Aufgabe von dieser Methode....

Das ist der richtige Hinweis! Die Methode Split ist nicht dafür geeignet. Ich habe seit Delphi5 eine eigene Methode die das alles berücksichtigt. Ich dachte die kann ich vergessen wenn Delphi das jetzt integriert hat.

Dankeschön.
Gruß Kostas

Sir Rufo 19. Jun 2016 16:57

AW: StringHelper Methode Split fehlerhaft?
 
Delphi hat etwas integriert was das alles berücksichtigt und das schon bevor es die Helper gab und nennt sich
Delphi-Quellcode:
TStringList

Kostas 19. Jun 2016 17:10

AW: StringHelper Methode Split fehlerhaft?
 
Hallo Sir Rufo,


in der Doku zu DeQuotedString eindeutig dass das übergebene Quote char am Anfang und am Ende entfernt wird.
In meinem Beispiel entfernt er alle.

Delphi-Quellcode:
Feld3 := '"(§§")"';

memo.Lines.Add(Feld3.DeQuotedString('"'));

ergibt: (§§) anstelle von (§§")
Hast du eine Idee warum?

Gruß Kostas

Sir Rufo 19. Jun 2016 17:15

AW: StringHelper Methode Split fehlerhaft?
 
Ja, wenn ich in den QuellText der Helper-Methode schauen würde :stupid:

Uwe Raabe 19. Jun 2016 17:43

AW: StringHelper Methode Split fehlerhaft?
 
Zitat:

Zitat von Kostas (Beitrag 1340552)
ich habe in einem Feldinhalt das: (§§") also Quote ich das Feld zu "(§§")"

Sollte das nicht eher "(§§"")" sein? Andernfalls wird das zweite Anführungzeichen als Quoteende interpretiert und das dritte wieder als Quoteanfang.

Zumindest ist es das, was
Delphi-Quellcode:
'(§§")'.QuotedString('"')
zurückgibt.

Uwe Raabe 19. Jun 2016 17:49

AW: StringHelper Methode Split fehlerhaft?
 
Ach ja: TStringHelper.Split produces results different from SplitString from StrUtils

Kostas 19. Jun 2016 18:05

AW: StringHelper Methode Split fehlerhaft?
 
Hallo Uwe,

Bei SplitString kann ich leider das Quote char nicht angeben.
Somit bringt das auch nichts.

Delphi-Quellcode:
  Feld1 := '"F1"';
  Feld2 := '"F2"';
  Feld3 := '"(§§")"';
  Feld4 := '"F4, F5"';
SplitString macht daraus fünf Felder anstelle von vier. Ist schon klar warum weil eben das Anführungszeichen nicht berücksichtigt werden.

Es geht um das einlesen von CSV-Dateien Trennzeichen ist das Komma und alle Felder sind mit Anführungszeichen umschlossen.
Somit erwarte ich für den String "F1","F2","(§§")","F4, F5"[CRLF] genau vier Felder
1=F1
2=F2
3=(§§")
4=F4, F5

Sir Rufo 19. Jun 2016 18:36

AW: StringHelper Methode Split fehlerhaft?
 
Nein, dein Ausgangs-String ist falsch.

Delphi-Quellcode:
Falsch_ := '"F1","F2","(§§")","F4, F5"';
Richtig := '"F1","F2","(§§"")","F4, F5"';

Uwe Raabe 19. Jun 2016 18:47

AW: StringHelper Methode Split fehlerhaft?
 
Zitat:

Zitat von Sir Rufo (Beitrag 1340568)
Nein, dein Ausgangs-String ist falsch.

Delphi-Quellcode:
Falsch_ := '"F1","F2","(§§")","F4, F5"';
Richtig := '"F1","F2","(§§"")","F4, F5"';

:thumb:
Genau das sollte mein Post darlegen. Der String ist einfach nicht korrekt gequoted.

Der Hinweis auf den QC-Eintrag sollte nur als Bestätigung dienen, daß es sich bei dem ersten Beispiel mit dem leeren letzten Feld vermutlich um einen Bug handelt.

Kostas 19. Jun 2016 19:03

AW: StringHelper Methode Split fehlerhaft?
 
Ja, ich habe jetzt das Problem erkannt. Der Text kann eigentlich nicht korrekt geparst werden, auch wenn es in meiner Methode bis jetzt immer funktioniert hat.
In meiner Methode suche ich nach Anführungszeichen Komme Anführungszeichen also "," oder "[CRLF] das hat bis jetzt "zufällig" funktioniert weil ich im Text nie das "," gehabt habe. :-)
Die Feldinhalte kommen eben aus einer Datenbank. Ein Anwender hat in ein Feld das (§§") eingegeben.
Das Problem ist ich darf das Anführungszeichen und Komma in den Feldinhalten nicht ersetzen und ich darf es auch nicht maskieren.
Es bleibt mir nur die Möglichkeit den Anwender aufzufordern das zu korrigieren.

Sehr interessant, seit Delphi5 Zeiten ist bis jetzt kein Anwender auf die Idee gekommen das "," einzugeben. :-)

Sir Rufo 19. Jun 2016 19:09

AW: StringHelper Methode Split fehlerhaft?
 
Was hat denn das mit dem Inhalt in der Datenbank zu tun?

Wenn überhaupt wird das falsch exportiert

Kostas 19. Jun 2016 19:25

AW: StringHelper Methode Split fehlerhaft?
 
Falsch Exportiert?

es gibt ein vorgeschriebenes Trennzeichen das Komma und jedes Feld muss mit Anführungszeichen exportiert werden.
Ich darf den Inhalt des Feldes nicht anfassen. Was könne ich jetzt noch machen?

[Edit] oh, es hat sich erledigt. Ich darf doch maskieren!

himitsu 20. Jun 2016 12:49

AW: StringHelper Methode Split fehlerhaft?
 
Zitat:

"(§§")"
Es kommt auch darauf an, wie gequotet wird.

In delphi wird meistens mit dem doppelten Quote-Zeichen das Zeichen selber geqoutet.

Also
Delphi-Quellcode:
"(§§"")"
und in Pascal halt
Delphi-Quellcode:
S := 'AGB''s \ blubb';
.
Und genau so verhällt sich auch das Quoting der TStringList.
In C-Sprachen wird dagegen gern das \ als Quotezeichen für Steuerzeichen benutzt, also
Delphi-Quellcode:
S := 'AGB\'s \\ blubb';
.
(Pascal kennt dagegen garkeine Steuerzeichen, außer dem ' oder halt ", während C auch Zeilenumbrüche ala '\n' und Co. versteht)

Sir Rufo 20. Jun 2016 13:55

AW: StringHelper Methode Split fehlerhaft?
 
Wenn wir von CSV sprechen, dann spricht man im Allgemeinen davon was in der RFC4180 so unverbindlich definiert wurde (ist kein Standard, weil niemand sich bei CSV auf einen Standard einigen konnte, wollte).
Zitat:

  1. If double-quotes are used to enclose fields, then a double-quote appearing inside a field must be escaped by preceding it with another double quote. For example:

    "aaa","b""bb","ccc"

Und auch wenn es kein allgemeingültiger Standard ist, tut man gut daran mit allen Parteien dieses Dokument als Standard zu deklarieren. Dann gibt es viel weniger Geschrei und "Ich-wars-nicht" Bekundungen.

Kostas 20. Jun 2016 16:00

AW: StringHelper Methode Split fehlerhaft?
 
Ich hatte den Hersteller kontaktiert um die Spezifikation zu besprechen. Dabei hat er erwähnt, ich darf auf keinen Fall die Feldinhalte verändern.
Meine Methode funktioniert zufällig weil ich alle drei Zeichen "," als Trennzeichen suche und nicht nur nach dem Komma. Ich habe den Export umgestellt
indem ich Anführungszeichen im Feldinhalt maskiere durch ein weiteres Anführungszeichen und exportiert. Die Fremdsoftware importiert es einwandfrei.
Also darf ich doch den Feldinhalt verändern. Somit habe ich umgestellt auf die TurboPower.Esentials.StStrL Methode.
Delphi-Quellcode:
function ExtractTokensL(const S, Delims: String;
                        QuoteChar : Char;
                        AllowNulls : Boolean;
                        Tokens    : TStrings) : Cardinal; overload;

Sir Rufo 20. Jun 2016 17:45

AW: StringHelper Methode Split fehlerhaft?
 
Das Verdoppeln des QuoteChars bzw. das Quoten selber verändert den Feldinhalt NICHT!

Bitte nicht Struktur und Daten durcheinander würfeln.

Das kann man gut vergleichen mit dem HtmlEncode, wo aus > ein &gt; gemacht werden muss weil das ansonsten nicht korrekt dargestellt wird.

Du hast das Transportmedium CSV und da gilt die Regel mit dem Quoten (s.o.), weil sonst am anderen Ende nur Grütze herauskommt -> Daten nicht lesbar oder werden falsch gedeutet.

Kostas 20. Jun 2016 21:26

AW: StringHelper Methode Split fehlerhaft?
 
Ja, habe ich verstanden.
Jetzt funktionierts und ich weis warum. :-)
Bisher hat es eben zufällig funktioniert.
Herzlichen dank nochmals.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:05 Uhr.

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