![]() |
Delphi-Version: 7
Erläuterung was "native unicode string" ist?
Hallo Wissende,
ich habe ein Riesen-Problem. Ich ziehe mir aus einer XML-Datei Teamnamen. Die XML-Datei ist in UTF-8 formatiert. Zum Anzeigen im Programm benutze ich die TntControls. Da sieht das alles super aus. Nun sende ich diese Inhalte (WideStrings und TWideStringlist) via TCP-Protokoll an eine Empfangende Software, die mir die inhalte visualisiert. Leider wird dabei aus dem gesendeten String: Widzew Łódź Das hier: Widzew Łó Es fehlen also Zeichen. Es kann nicht an der Schriftart liegen, da die Anbieter der Rendering-software auch einen Designer haben. Wenn ich dort den String reinkopiere, wird der Inhalt korrekt gerendert. Es muss also an der Übermittlung irgendwo haken. Der Programmierer, den ich daraufhin angeschrieben habe, teilte mir folgendes mit: "Please double check that the value passed to Tk5 has proper value. It should be native unicode string, not UTF-8." Ich bin jetzt natürlich etwas ratlos und würde mich über ein paar Ratschläge freuen. |
AW: Erläuterung was "native unicode string" ist?
Für den Zweck würde sich zwar eine neuere Delphiversion (2009+) als die bei dir angegebene Version Delphi 7 wegen voller Unicodeunterstützung besser eignen, aber nichtsdestotrotz sollten WideStrings auch in Delphi 7 bereits funktionieren, da sie vom Betriebssystem verwaltet werden.
WideStrings sind auch nicht UTF-8, sondern benutzen tatsächlich die 2 Byte pro Zeichen. Kannst du vielleicht einmal exakt die Bytes posten wie du sie via TCP versendest? Und wie verschickst du diese? |
AW: Erläuterung was "native unicode string" ist?
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo Sebastian,
meine Angaben waren wohl nicht ganz korrekt. Also die Strings aus dem XML visualisiere ich als WideStrings z.B. in einem TTntEdit Das Sammeln der Daten geschieht über TWideStrinlists aus der Unit JclUnicode. Dann übergebe ich die Liste an eine selbst geschriebene Komponente, die die Daten dann an ein ComObjekt (GSTK5Lib_TLB) übergibt. Das Ding connected sich zum Renderer. Der Fehler liegt wohl definitiv auf meiner Seite, nur weiss ich noch nicht genau wo. Ich könnte den Code der Komponente und das Sender der Daten hier Posten, aber die Komponente selbst hat 900 Zeilen Code. Der Programmierer hat mir noch einen Link zu den ![]() Hier aber mal die XML-Datei, aus der ich auslese. Was mich eben auch verwirrt, ist der Umstand, dass die Sonderzeichen nicht grundsätzlich NICHT funktionieren, sondern es nur partiell zu Problemen kommt. |
AW: Erläuterung was "native unicode string" ist?
Unicode Zeichen im UTF-8 Format benötigen zwischen 1-4 Byte. Womöglich werden einige Bytes nicht mitgeschickt weil die Längenberechnung des Strings nicht stimmt. SizeOf(...) wäre hier ganz falsch.
UTF-16 braucht 2-4 Bytes, die Länge muss auch hier berechnet werden. Kann passieren, wird aber oft vernachlässigt. Ich nehme wohl an, dass er die Daten in diesem Format erwartet, denn es würde WideString entsprechen. Dann gibt's noch UTF-32, das hat immer 4 Byte. |
AW: Erläuterung was "native unicode string" ist?
Zitat:
Wenn du dort einen Haltepunkt setzt: Sind die Daten dort noch korrekt? |
AW: Erläuterung was "native unicode string" ist?
ich checks mal und melde mich dann wieder.
danke erstmal soweit. |
AW: Erläuterung was "native unicode string" ist?
Also ich habs jetzt mal überprüft.
Der Aufruf in der TLB_Unit sieht so aus:
Delphi-Quellcode:
Sprich ich übergebe den Namen des Objektes, dann den Typ (text) und dann den Inhalt des Objektes.
procedure set_(const address: WideString; const attrName: WideString; value: OleVariant); safecall;
Der Aufruf dieser Procedure in meiner Komponente läuft so ab:
Delphi-Quellcode:
TextString, LogoString sind vom Typ her TWideStringlist
//AUSSCHNITT
//hier werden die texte aus der TWideStringlist einzeln übergeben for i := 0 to TextString.Count - 1 do loc_AkiTitle.set_(TextString.Names[i],'Text',TextString.Values[TextString.Names[i]]); //hier werden die logos aus der TWideStringlist einzeln übergeben for i := 0 to LogoString.Count - 1 do loc_AkiTitle.set_(LogoString.Names[i],'FileName',LogoString.Values[LogoString.Names[i]]); //hier werden zusätzliche Eigenschaften aus einer TWideStringlist einzeln übergeben for i := 0 to PropList.Count - 1 do loc_AkiTitle.set_(PropList.Items[i].str_Name,PropList.Items[i].str_Type,PropList.Items[i].str_Value); Also sollte das doch so passen. Oder? Obwohl, ich sehe gerade, dass der eigentliche Inhalt vom Typ her value: OleVariant ist. Kann hier die Ursache für das Problem liegen? Inhalte, die ich aus Edits hole, kommen ausschließlich von TTntEdits. Die TWideStringlist habe ich mir fertig von der JCL geborgt. Ich hoffe, dass das eventuell etwas hilft, mir bei meinem Problem zu helfen? |
AW: Erläuterung was "native unicode string" ist?
Hmm, testweise könntest du TextString.Values[TextString.Names[i]] usw. einmal in WideString Variablen zwischenspeichern bevor du es übergibst.
|
AW: Erläuterung was "native unicode string" ist?
Nur, um kurz mal sicher zu gehen.
Du meinst, ich soll mir die 2 übermittelten Werte jeweils in einer WideString-Variablen zwischenspeichern und dann der TLB-Funktion übergeben? Wäre dabei was anders? Oder soll ich mir das dann loggen? Was ist der Hintergrund Deines Vorschlags? |
AW: Erläuterung was "native unicode string" ist?
So nebenbei würde ich auch 'ValueFromIndex' verwenden. Tut zwar nix zur Sache, ist aber schneller und übersichtlicher.
Delphi-Quellcode:
for i := 0 to TextString.Count - 1 do
loc_AkiTitle.set_(TextString.Names[i],'Text',TextString.ValueFromIndex[i]); |
AW: Erläuterung was "native unicode string" ist?
Zitat:
|
AW: Erläuterung was "native unicode string" ist?
Nicht nur deshalb. Dadurch wird sichergestellt, dass ein neuer WideString als direkte WideString Variable an den OleVariant Wert übergeben wird.
Eigentlich sollte das keinen Unterschied machen. Aber man weiß ja nie... |
AW: Erläuterung was "native unicode string" ist?
Zitat:
aber trotzdem danke für den Optimierungsversuch. |
AW: Erläuterung was "native unicode string" ist?
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Delphi-Quellcode:
Habe mir einen Haltpunkt gesetzt und bin mit der Maus über die Variablen gefahren. Scheinbar sind die Hints NICHT UniCode, da ich viele ? zu sehen bekam.
var
i : integer; sName, sValue : WideString; begin ... for i := 0 to TextString.Count - 1 do begin sName := TextString.Names[i]; sValue := TextString.Values[TextString.Names[i]]; //loc_AkiTitle.set_(TextString.Names[i],'Text',TextString.Values[TextString.Names[i]]); loc_AkiTitle.set_(sName,'Text',sValue); end; Damit Ihr mal seht, wie sich das Problem visuell darstellt, hier mal ein Bildanhang. Links seht Ihr ein TTnTMemo, welches ja UniCode kann. Komisch ist hier schon in der Ansicht, dass in Zeile 4 statt subline der Code etwas komisch aussieht. Die 1. wird rechts im Preview auch nicht angezeigt 5 bei Cracovia das hier steht -> Cracoⅵa und in der Anzeige nur Cracoa Bin kurz vorm verzeifeln. |
AW: Erläuterung was "native unicode string" ist?
Ich habe nun mal die WideStringList gespeichert.
Sieht leider nicht gut aus. Das Problem ist also definitiv auf meiner Seite: header=EKSTRAKLASA subl㏌e=⒈ kolejka team_a=Cracoⅵa Kraków team_b=Legia Warszawa Das sieht nicht wirklich nach UniCode aus. Muss ich vielleicht bei den TNT-Controls irgendwas am Charset einstellen oder der WideStringlist noch eine spezielle Eigenschaft verpassen? |
AW: Erläuterung was "native unicode string" ist?
Zitat:
Das Problem ist wie du bemerkt hast natürlich, dass die Delphi IDE durch die fehlende Unicodeunterstützung auch keine Unicodestrings beim Debuggen auswerten kann... Was du versuchen kannst um definitiv festzustellen, ob die Strings falsch sind, ist, dass du diese einfach einmal ausgibst:
Delphi-Quellcode:
Das sollte auch mit Delphi 7 problemlos funktionieren.
MessageBoxW(0, PWideChar(sName), 'Test: sName', 0);
MessageBoxW(0, PWideChar(sValue), 'Test: sValue', 0); |
AW: Erläuterung was "native unicode string" ist?
Sorry, wenn ich mich dämlich anstelle, aber mein Delphi kennt kein MessageBoxW.
|
AW: Erläuterung was "native unicode string" ist?
Dann fehlt die Unit Windows in der uses Klausel.
|
AW: Erläuterung was "native unicode string" ist?
Jo, jetzt kommen die MessageBoxen.
--------------------------- Test: sValue --------------------------- Cracoⅵa Kraków --------------------------- OK --------------------------- ist der Inhalt. Hier ist auch wieder das vi im Teamnamen so "komisch". Und so "baue" ich den Code zusammen:
Delphi-Quellcode:
Die Messagbox kommt aus einer UnterRoutine von TS_AKI_ProviderUC1.ShowGraphic.
procedure Tmatchid.btn_showClick(Sender: TObject);
begin //hinzufügen der strings TextString.Add('header=' + ed_header.Text); TextString.Add('subline=' + ed_subline.Text); TextString.Add('team_a=' + ed_team_a.Text); TextString.Add('team_b=' + ed_team_b.Text); TextString.Add('footer_1=' + ed_footer_1.Text); TextString.Add('footer_2=' + ed_footer_2.Text); TextString.Add('footer_3=' + ed_footer_3.Text); //schicken der inhalte zum laden der grafik form1.TS_AKI_ProviderUC1.ShowGraphic('match_id.gse',1,TextString,LogoString,PropList,0,'IN',True); end; Dort ist alles auf WideString und TWideStringlist eingestellt. |
AW: Erläuterung was "native unicode string" ist?
Funktioniert es denn, wenn du den Inhalt der Editfelder direkt per MessageBoxW ausgibst?
(Gibt es vielleicht noch eine andere Eigenschaft als Text? Also ist Text wirklich WideString?) Lass doch den Unsinn mit der TWideStringList weg. Wenn du mehrere Werte nicht einzeln übergeben willst, nimm einen Record. Aber das ganze zu einer Liste verwursten und dann wieder auseinanderzubasteln ist Blödsinn... |
AW: Erläuterung was "native unicode string" ist?
Hm, ich glaube wir nähern uns dem Ziel, denn
//einzel-ausgabe aus dem Control zeigt mir den Namen korrekt an MessageBoxW(0, PWideChar(ed_team_a.Text), 'Test: sName', 0); //stringlist-ausgabe, zeigt mir den Namen verwurschtelt an MessageBoxW(0, PWideChar(TextString.Text), 'Test: sName', 0); also ist wohl die stringliste, wie von dir schon vermutet, das problem. jetzt stehe ich natürlich vor nem riesenproblem, weil ich seit ca. 4 jahren alle projekte mit TStringlisten fahre, da sich die daten herrlich sammeln lassen. in der komponente sind ja mehr als eine sub-routine, die alle auf das benutzen der Stringliste abgestimmt sind. Und ganz ehrlich sehe ich gerade den Baum vor lauter Wald nicht. Record ist mir klar, aber eine Liste davon oder einen dynmaischen Record erzeugen, wo ich auch schön den Namen des Objekte und seinen Inhalt übergeben und später einfach auslesen kann, treibt mir gerade viele Fragezeichen über den Kopf. Grübel... Und Zitat:
|
AW: Erläuterung was "native unicode string" ist?
Zitat:
Denn der Compiler kann dir dort bei Tippfehlern nicht helfen, so dass sich da leicht versteckte Probleme einschleichen können. Qualitativ guter Quelltext sieht anders aus... Ein Beispiel nach deinem Quelltext:
Delphi-Quellcode:
Ganz nebenbei zum Stil:
type
TGraphicContents = record Header: WideString; SubLine: WideString; TeamA: WideString; TeamA: WideString; Footer1: WideString; Footer2: WideString; Footer3: WideString; end; procedure Tmatchid.btn_showClick(Sender: TObject); var GraphicData: TGraphicContents; begin // Setzen der Daten GraphicData.Header := ed_header.Text; GraphicData.SubLine := ed_subline.Text; GraphicData.TeamA := ed_team_a.Text; GraphicData.TeamB := ed_team_b.Text; GraphicData.Footer1 := ed_footer_1.Text; GraphicData.Footer2 := ed_footer_2.Text; GraphicData.Footer3 := ed_footer_3.Text; //schicken der inhalte zum laden der grafik form1.TS_AKI_ProviderUC1.ShowGraphic('match_id.gse', 1, GraphicData, LogoString, PropList, 0, 'IN', True); end; Unterstriche in Bezeichnern sind äußerst unüblich, es gibt auch Groß- und Kleinschreibung. Statt ed_header wäre edHeader oder edtHeader schöner (auch wenn manche die ungarische Notation an sich schlecht finden, ich finde sie bei Komponenten sehr sinnvoll). |
AW: Erläuterung was "native unicode string" ist?
Danke für Dein Beispiel und die anderen belehrenden Hinweise. Ich werde versuchen Sie zu beherzigen.
Ich hatte absichtlich geschrieben, dass ich es dynamisch brauche, weil ich ja mehr als eine Struktur von Inhalten übermitteln muss. Sagen wir, ich muss ca. 40 verschiedene Grafiken mit unteriedlicher inhaltlicher Struktur anzeigen. Soll ich nun 40 verschiedene Records "bauen"? Z.B. habe ich auch so was hier am Start:
Delphi-Quellcode:
Die Komponente weiss im Prinzip nix von alledem und arbeitet nur stur und doof ab, was ich ihr zu füttern gebe. Da liegt meiner Meinung nach der Vorteil. Ich kann völlig frei und flexibel die Stringliste erstellen und übergeben und die Komponente arbeitet alles ab, wenngleich mir auch da schon Probleme auftraten mit falschen Namen in der Stringlist. In dem Punkt bin ich komplett bei Dir.
procedure TForm1.btn_show_matchesClick(Sender: TObject);
var i : integer; begin TextString.Add('header=' + ed_header_rounds.Text); for i := 1 to 8 do begin //hier werden 48 inhalte in die strinlist geschrieben //geht das auch so einfach mit nem record? LogoString.Add('logo_a'+ inttostr(i)+'=' + (FindComponent('cmb_ro_team_a' + inttostr(i)) as TComboBox).Text); LogoString.Add('logo_b'+ inttostr(i)+'=' + (FindComponent('cmb_ro_team_b' + inttostr(i)) as TComboBox).Text); TextString.Add('team_a'+ inttostr(i)+'=' + (FindComponent('ed_ro_team_a' + inttostr(i)) as TdxDNEdit).Text); TextString.Add('team_b'+ inttostr(i)+'=' + (FindComponent('ed_ro_team_b' + inttostr(i)) as TdxDNEdit).Text); TextString.Add('result_a'+ inttostr(i)+'=' + (FindComponent('ed_ro_res_a' + inttostr(i)) as TdxDNEdit).Text); TextString.Add('result_b'+ inttostr(i)+'=' + (FindComponent('ed_ro_res_b' + inttostr(i)) as TdxDNEdit).Text); end; TS_AKI_ProviderUC1.ShowGraphic('rounds.gse',1,TextString,LogoString,PropList,0,'IN',True); end; |
AW: Erläuterung was "native unicode string" ist?
Zitat:
Delphi-Quellcode:
Wobei du solche konstanten Namen wie cmb_ro_team_a am besten als Konstanten deklarierst, dann kannst du Probleme oder Namensänderungen bei Komponenten viel schneller überblicken.
type
TDemo = record LogoA: array[1..8] of WideString; LogoB: array[1..8] of WideString; ... end; MyData.LogoA[i] := (FindComponent('cmb_ro_team_a' + IntToStr(i)) as TComboBox).Text; MyData.LogoB[i] := (FindComponent('cmb_ro_team_b' + IntToStr(i)) as TComboBox).Text; Ganz so dynamisch ist ein Record natürlich nicht, aber es gibt auch variante Records. Leider gehen die wiederum nicht mit WideStrings. Und ein Dictionary existiert wegen der fehlenden Generics bei deiner alten Delphiversion auch noch nicht. Du würdest dir das Leben an vielen Stellen leichter machen, wenn du dir Delphi XE kaufen würdest. ;-) Das hier müsste aber auch schon bei Delphi 7 gehen...
Delphi-Quellcode:
Da kannst du auch keine Tippfehler machen und das sollte so ca. dem entsprechen was du an dynamischen Inhalten brauchst.
type
TTest = (tstOne, tstTwo); TExample = record DataName: WideString; MyData: array[TTest] of WideString; end; var MyTest: TExample; begin MyTest.MyData[tstOne] := 'a'; MessageBoxW(0, PWideChar(MyTest.MyData[tstOne]), 'Test', 0); Insgesamt sieht das ganze aber eher so aus als wären Klassen sehr viel besser geeignet... Denn da kannst du für die verschiedenen Datentypen entsprechend abgeleitete Klassen erstellen und bist da sehr viel flexibler, kannst aber die Basisfunktionalitäten dennoch gemeinsam kapseln. |
AW: Erläuterung was "native unicode string" ist?
Hallo Sebastian,
erstmal entschuldigung für die späte antwort. aber da das projekt ziemlich drängt, war ich busy. ich habe in der zwischenzeit eine lösung gefunden, die weiterhin auf Strinlisten beruht. scheinbar ist so, dass die widestrings der tntcomponente nicht zusammen passen mit den tsringlisten der jcl. ich habe bruno von tms kontaktiert, da die ja die tntcontrols übernommen haben und er hat mir vorgeschlagen es einfach mal mit den TTntStringlist zu versuchen. das hat dann auf anhieb geklappt. ich bleibe also erstmal, bis ich wieder etwas luft habe, bei der art und weise der internen datenverarbeiteung, wollte dich aber 1. wissen lassen, dass das problem gelöst wurde und 2. dass ich deinen ansatz grundsätzlich gut finde und ich überlege, wie ich das in zukunft für weitere projekte implementieren kann. also nochmals vielen dank für dein engagement und die angebotene hilfe! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:06 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