Problem mit Multibyte-Zeichen

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Problem mit Multibyte-Zeichen

Beitrag von Patito »

mse hat geschrieben:@Patio:
Darum geht es ja gar nicht. Es geht um die Suche nach *bekannten* Zeichen. Ein Problem bestünde erst dann, wenn das Unicode Consortium das Zeichen 'ä' z.B. vom jetzigen $e5 auf $12345 verlegen würde. Ich versuche diesen Umstand schon mehrere Jahre "rüber zu bringen", scheinbar ist mir das immer noch nicht gelungen. :-)


Das Beispiel das ich letztin gesehen habe, war so ein if Label.Caption = "Playbutton".
Prüfen auf Spezialsymbole als Caption dürfte in deinen Problembereich fallen.

Im Code will ich nicht bei jedem Char nachschauen müssen, ob es jetzt auch wirklich funktioniert.
Wenn ein Syntax-Konstrukt nicht immer zuverlässig funktioniert, habe ich von dem Konstrukt keinen Vorteil.

Dein Ansatz hat sicher gewisse Vorteile (die ich nicht ganz so toll finde).
Mein Hauptproblem mit deinem Ansatz sind eher die Nachteile, die man mit einem internen 16-bit Typ einkauft.

"Konvertieren an den Grenzen der Anwendung" war mal so ein Mantra bei Delphi, von dem ich überhaupt nichts halte.
Wenn die Daten intern anders sind als man sie extern braucht, ist das zum programmieren ein Krampf..
Mich da von etwas anderem zu überzeugen ist sehr sehr schwer...

Ernst gemeinte Frage: Wie schnell kann man ASCII nach UTF-16 wandeln (MB/s)?

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Problem mit Multibyte-Zeichen

Beitrag von mse »

Patito hat geschrieben:Das Beispiel das ich letztin gesehen habe, war so ein if Label.Caption = "Playbutton".

Wie ist "Playbutton" definiert?
Ernst gemeinte Frage: Wie schnell kann man ASCII nach UTF-16 wandeln (MB/s)?

Für GUI-Texte fällt das nicht stark ins Gewicht, da irgendwo in der Anzeigekette sowieso auf UCS4 gewandelt wird. utf-16 -> UCS4 ist einfacher als utf-8 -> UCS4 so dass ein Teil der Aufwendung wieder zurückgewonnen wird speziell auf den meisten GUI-Systemen ausser GTK welche an der Schnittstelle sowieso utf-16 verwenden.

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Problem mit Multibyte-Zeichen

Beitrag von Patito »

mse hat geschrieben:Wie ist "Playbutton" definiert?


Ist doch wurscht. Nimm einfach irgendein Button-Caption mit z.B. einem Symbol aus
http://www.unicode.org/charts/PDF/Unico ... -1F300.pdf

mse hat geschrieben:Für GUI-Texte fällt das nicht stark ins Gewicht, da irgendwo in der Anzeigekette sowieso auf UCS4 gewandelt wird. utf-16 -> UCS4 ist einfacher als utf-8 -> UCS4 so dass ein Teil der Aufwendung wieder zurückgewonnen wird speziell auf den meisten GUI-Systemen ausser GTK welche an der Schnittstelle sowieso utf-16 verwenden.


Für GUI-Texte ist es ja auch egal - daher hat UTF-16 da auch keinerlei Vorteil.
Bei mir taucht in Profilern das Einlesen von Strings aus einer Datenbank spürbar auf.

Meine grobe Rechnung für UTF-16 sieht erst mal so aus:
- ASCII/Ansi einlesen
- noch einmal doppelt soviel Speicher für UTF-16 besorgen
- alle Buchstaben kopieren

-> Geschwindigkeits-Verlust durch UTF-16: Jenseits von Faktor 3

BeniBela
Beiträge: 308
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: Problem mit Multibyte-Zeichen

Beitrag von BeniBela »

mse hat geschrieben:Und du glaubst tatsächlich, dass das Unicode Consortium in ein paar Jahren 'ä' von $e5 auf z.B. $12345 verlegen wird? Ernsthaft?



Ih meine, dass man jetzt vielleicht nach $e5 suchen will, später aber auch mal nach $1f401...

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Problem mit Multibyte-Zeichen

Beitrag von mse »

Patito hat geschrieben:
mse hat geschrieben:Wie ist "Playbutton" definiert?


Ist doch wurscht. Nimm einfach irgendein Button-Caption mit z.B. einem Symbol aus
http://www.unicode.org/charts/PDF/Unico ... -1F300.pdf

??? Aber wo liegt denn das Problem?

Code: Alles auswählen

 
 if Label.<UnicodeString>Caption = <UnicodeString>Playbutton then
 

oder wie gewohnt

Code: Alles auswählen

 
 if Label.<Utf8String>Caption = <Utf8String>Playbutton then
 

funktionieren doch beide?
Meine grobe Rechnung für UTF-16 sieht erst mal so aus:
- ASCII/Ansi einlesen
- noch einmal doppelt soviel Speicher für UTF-16 besorgen
- alle Buchstaben kopieren

-> Geschwindigkeits-Verlust durch UTF-16: Jenseits von Faktor 3

Wenn du möchtest kannst du die Probe aufs Exempel mit meiner SQLDB Implementation machen. Die arbeitet im Dataset mit UnicodeString, die originale FPC Version mit 8bit record buffer. ZEOS 7.2 benützt nun übrigens ein Ähnliches Konzept wie MSEgui.
Auch der "doppelte Speicherbedarf" ist relativ. Um 'abc' in einer Variablen zu speichern braucht 64Bit FPC 2.7.1 32 Bytes als AnsiString und 36 Bytes als UnicodeString. Bei beiden kommt noch weiterer Speicher im memorymanager dazu.
Texte die nicht in der GUI benötigt werden muss man ja nicht wandeln wenn keine Notwendigkeit dazu besteht.
Zuletzt geändert von mse am Do 18. Sep 2014, 11:22, insgesamt 1-mal geändert.

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Problem mit Multibyte-Zeichen

Beitrag von mse »

BeniBela hat geschrieben:Ih meine, dass man jetzt vielleicht nach $e5 suchen will, später aber auch mal nach $1f401...

Dann wird dich der Compiler höflich darauf hinweisen, dass $1f401 nicht in UnicodeChar Platz findet und man stattdessen UnicodeString verwenden sollte. ;-)

BeniBela
Beiträge: 308
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: Problem mit Multibyte-Zeichen

Beitrag von BeniBela »

mse hat geschrieben:Dann wird dich der Compiler höflich darauf hinweisen, dass $1f401 nicht in UnicodeChar Platz findet und man stattdessen UnicodeString verwenden sollte. ;-)


Nicht wenn man nach einer Usereingabe sucht

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Problem mit Multibyte-Zeichen

Beitrag von mse »

BeniBela hat geschrieben:Nicht wenn man nach einer Usereingabe sucht

Dann ist das Zeichen nicht *bekannt* und darum geht es hier ja nicht.
Im Fall der Usereingabe liegt der Text als String vor und ob der als UnicodeString oder UTF8String gespeichert ist spielt kaum eine Rolle. pos() funktioniert mit beiden.

Dee
Beiträge: 54
Registriert: Do 10. Jul 2014, 20:56
OS, Lazarus, FPC: Windows 10 Pro 64-bit, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: Ryzen 5 2600

Re: Problem mit Multibyte-Zeichen

Beitrag von Dee »

Hier bin ich noch mal.

Ich störe nur ungern eure Diskussion, aber ich würde gerne wissen, wie man nun Zeichen wie ä in ein Char speichern kann.

Ich habe mal folgendes ausprobiert:

Code: Alles auswählen

 
var
  s: WideString;
  c: Char;
begin
  s := UTF8Decode('äüö');
  c := UTF8Encode(s)[1];
  ShowMessage(c) // zeigt nichts an     
end;
 


Was muss man machen, damit das Zeichen gespeichert wird?

MfG
-- Dee

BeniBela
Beiträge: 308
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: Problem mit Multibyte-Zeichen

Beitrag von BeniBela »

Ich nehme dafür immer integer statt char...

Passt besser rein


Übrigens, kennt ihr schon CESU-8? Der absolute Alptraum, die Nachteile von UTF-8 und UTF-16 kombiniert, ohne irgendwelche Vorteile

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Problem mit Multibyte-Zeichen

Beitrag von theo »

Dee hat geschrieben:Was muss man machen, damit das Zeichen gespeichert wird?


Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var wc:WideChar;
begin
 wc:=UTF8Decode('ä')[1];
 ShowMessage(UTF8Encode(wc));
end

mse
Beiträge: 2013
Registriert: Do 16. Okt 2008, 10:22
OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
CPU-Target: x86,x64,ARM

Re: Problem mit Multibyte-Zeichen

Beitrag von mse »

Für FPC 2.6.4:
UTF8Decode() ist in inc/ustringh.inc so deklariert:

Code: Alles auswählen

 
function UTF8Decode(const s : UTF8String): UnicodeString;
 

Also:

Code: Alles auswählen

 
var
  s: UnicodeString;
  c: UnicodeChar;
begin
  s := UTF8Decode('äüö');
  c := s[1];
  ShowMessage(UTF8Encode(c))
end;
 

Man kann dem Compiler auch mitteilen, dass die Quelle in utf-8 geschrieben ist, dann werden Textkonstanten automatisch "richtig" gespeichert: *

Code: Alles auswählen

 
{$codepage utf8}
procedure tmainfo.exe(const sender: TObject);
var
  s: UnicodeString;
  c: UnicodeChar;
begin
  s := 'äüö';
  c := s[1];
  ShowMessage(UTF8Encode(c))
end;
 

Dasselbe erreicht man durch den Compiler Parameter -Fcutf8, dann braucht es {$codepage utf8} nicht. *
Das UTF8Encode(c) ist darum notwendig, da der Compiler davon ausgeht, dass man AnsiString in der 8-Bit Systemcodierung haben möchte, Lazarus aber immer utf-8 erwartet und Windows in der Regel nicht utf-8 als 8-bit Systemcodierung verwendet. Auf einem Linux mit utf-8 Locale ist es nicht notwendig.
Auf Delphi und MSEgui welche grundsätzlich mit UnicodeString arbeiten vereinfacht sich die Sache auf:

Code: Alles auswählen

 
{$codepage utf8}
procedure tmainfo.exe(const sender: TObject);
var
  s: UnicodeString;
  c: UnicodeChar;
begin
  s := 'äüö';
  c := s[1];
  ShowMessage(c)
end;
 

Auf FPC 2.7.1 sollte für Lazarus das UTF8Encode(c) ebenfalls nicht notwendig sein, da dort der Compiler weiss, dass der von Lazarus verwendete UTF8String utf-8 codiert sein muss. Das habe ich aber nicht geprüft, da ich 2.7.1 nicht verwende.
Edit1:
* Dies verträgt sich für FPC 2.6.4 auf Windows mit der Lazarus Strategie "utf-8 in AnsiString" nicht.
Edit2:
* verträgt sich auch für FPC 2.7.1 nicht ohne weiteres auf Windows mit Lazarus da "ShowMessage()" einen "string" und keinen "UTF8String" erwartet. "string" = "AnsiString(CP_ACP)" für FPC 2.7.1, das heisst man muss zusätzlich "DefaultSystemCodePage(CP_UTF8)" aufrufen um die gewünschte Codierung zu erhalten.
Eigentlich sollten Lazarus und die Lazarus Nutzer überall einen speziellen "LazString" statt "string" verwenden welcher dann zentral an den gewünschten System-Stringtyp gebunden werden könnte.
Zuletzt geändert von mse am Do 25. Sep 2014, 07:09, insgesamt 1-mal geändert.

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Problem mit Multibyte-Zeichen

Beitrag von Patito »

Ich habe mal den Verdacht, dass hier echt viel Schrott geschrieben wird...

Dieses Gefuzzel mit UnicodeChar/WideChar funktioniert doch gar nicht für beliebige Unicode-Zeichen.
Das ist doch genau derselbe Mist wie mit Char.

Wenn man einen Unicode-Text hat und sich mit Char oder WideChar (=UnicodeChar) einzelne Teile aus einem String holt,
kann man sich nie sicher sein, ob man ein einzelnes darstellbares Zeichen bekommt.
Man kriegt manchmal nur ein Fragment eines Zeichens (die ersten 8 bzw 16 Bit).

Wenn man darstellbaren Text haben will, benötigt man echte Substrings und keine Chars
Mit Chars zu arbeiten funktioniert so nicht, und wenn man mit Utf8Decode, UnicodeChar und
Widestrings rumwurstelt, wird das doch nicht gelöst, sondern nur verschleiert.

?!

Benutzeravatar
theo
Beiträge: 10497
Registriert: Mo 11. Sep 2006, 19:01

Re: Problem mit Multibyte-Zeichen

Beitrag von theo »

@mse: systemh.inc: UnicodeChar = WideChar;
Mein Beispiel macht genau dasselbe. Der Rest deines Textes verwirrt mehr als er klärt, aber das ist vermutlich deine Absicht.

@patito: Du hast im Prinzip recht, für den Hausgebrauch ist es aber mMn zulässig, von UCS-2 auszugehen.
Normalisierung steht immer im Raum, ist aber für den anwendungsinternen Gebrauch auch nicht relevant, d.h. kann man an den Schnittstellen ausbügeln.

Patito
Beiträge: 203
Registriert: Di 22. Sep 2009, 13:08
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: Problem mit Multibyte-Zeichen

Beitrag von Patito »

@Theo: Wenn man schon so viel Aufwand betreibt, dass man Sachen umcodiert, sollte es dann doch wenigstens richtig funktionieren.
Heutzutage voll auf UCS-2 abzufahren ist doch kein Hausgebrauch, sondern eher häusliche Gewalt.

Deine Lösung kann man zwar als schnelle Bastellösung durchgehen lasser, aber insgesamt würde ich doch eher "Daumen runter" dazu sagen.

Antworten