Erkennen ob das Zeichen ein UTF8 Zeichen ist

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von mschnell »

pluto hat geschrieben:Dann bin ich genauso weit wie Vorher. :(
Wieso. Ist doch ziemlich klar:

Mit Widestring musst du mit UTF8Encode und UTF8Decode hin und her konvertieren, wenn Du in Hochkommata eingeschlossene Texte zuweist und wenn Du mit LCL-Funktionen und Properties arbeitest. Es gibt aber einen Type WideChar mit dem Du Vergeliche und auch "case" machen kannst.

Mit UTF8Strings kannst Du nicht "normal" (d.h. ohne genau zu wissen wie Unicode funktioniert) mit Funktionen wie length, pos, copy oder delete arbeiten. Es gibt keinen Type UTF8Char. Dafür ist nun die Kommunikation mit der LCL einfach.

Mit Ländercode spezifischen ANSIStrings zu arbeiten ist mit dem neuen Lazarus nicht einfach, weil die LCL eine UTF8 API hat und in Hochkommata eingeschlossene Texte als UTF8 ausgegeben werden. Man hat dabei keine Möglichkeit zwischen UTF8String und ANSIString zu unterscheiden. Wenn Du das willst nimmst Du wohl besser das alte Lazarus oder das alte (Turbo-) Delphi.

Wenn Du ohne manuelle Konvertierungen mit 16 Bit Unicode (Widestring) arbeiten willst (damit pos etc "normal" geht und es einen entsprechenden Char Typ gibt) musst Du mit MSEGUI oder Delphi 2009 arbeiten oder auf eine zukünftige Lazarus-Version warten.

-Michael
Zuletzt geändert von mschnell am Di 6. Jan 2009, 23:53, insgesamt 2-mal geändert.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von mschnell »

pluto hat geschrieben:c:=UTF8Length(str);

macht keinen Sinn. Ein UTF-8 String sollte nicht in einem WideString sein.

Warum nicht ? So erhalte ich die richtige anzahl der Zeichen im String auch wenn Umlaute da sind.
Dann ist es eben nicht UTF8, sondern UCS2.
-Michael

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

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von theo »

pluto hat geschrieben: PS: Die heutige Preisfrage: Wie lange wird wohl dieser Thread noch laufen bis keiner mehr Antworten ? Was meint ihr :mrgreen:
Also wenn ich sagen würde "bis du's begriffen hast" würden es wohl noch hundert Seiten werden.... ;-)

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von mschnell »

pluto hat geschrieben: Wenn Umalaute/Sonderzeichen im String erhalten sind gibt es bei s[5] was falsches zurück
Ob das richtig oder falsch ist kommt darauf an, was Du als "falsch" und was Du als "Zeichen" definierst. UTF8Strings werden in Codes und nicht in Codepoints gezählt. ein Umlaut ist ein Unicode-Codepoint (Was Du vermutlich mit "Zeichen" meinst), aber zwei UTF8-Codes.

-Michael
Zuletzt geändert von mschnell am Di 6. Jan 2009, 23:54, insgesamt 1-mal geändert.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von mschnell »

theo hat geschrieben: Sonst hast du einfach einen UTF-8 String auf DoubleByte aufgeblasen. Ausserdem weisst du dann gar nicht mehr, in welcher Form der String nun vorliegt.
Eben in gar keiner gültigen Codierung. Ich finde Pluto hat recht, dass es ein Bug ist, dass der Compiler das "auf DoubleByte aufgeblasen" überhaupt macht.
-Michael
Zuletzt geändert von mschnell am Di 6. Jan 2009, 23:56, insgesamt 2-mal geändert.

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

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von theo »

mschnell hat geschrieben:Eben in gar keiner gültigen Codierung. Ich finde Pluto hat recht, dass es ein Bug ist, dass der Compiler das tut.
Mag sein, dass der Compiler das tun sollte, sobald ein ensprechender Datentyp definiert ist, aber red jetzt Pluto nicht ein, er habe recht mit seinem Wirrwarr.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von mschnell »

"auf DoubleByte aufgeblasen" macht er, weil er automatisch ANSI nach UCS2 umcodiert und nicht UTF8 nach UCS2. Ein Problem entsteht dadurch, dass Stringkonstanten in Hochkomma als UTF8 entstehen und eben nicht als ANSI oder Widestring. Leider hilft es auch nicht den 8-Bit Stringtyp korrekt als UTF8String zu definieren, weil der Compiler bekanntermaßen nicht zwischen ANSIString und UTF8String unterscheidet.

Einmal wird für die Kodierung des einzigen (weil untereinander nicht unterscheidbaren) 8-Bit String Typs automatisch ANSI angenommen, ein andermal wird automatisch UTF8 erzeugt. Alles nicht unbedingt "falsch" sondern "by Design", aber in dieser Kombination sehr unschön und eben überhaupt nicht Pluto-tauglich.

-Michael

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von mschnell »

theo hat geschrieben:
mschnell hat geschrieben:
theo hat geschrieben:Hast du irgendwelche Anhaltspunkte, was denn konkret in der Pipeline ist?
Bevor ich mir wieder die Finger verbrenne: Schaue Dir das Backlog der FPC Developers Mailing List an !
Wie gesagt, finde ich da keinen konkreten Plan, von einer Roadmap ganz zu schweigen.
Vielleicht weiß marcov mehr ??? !!!
-Michael

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

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von theo »

Ich weiss das alles mschnell wir haben das bis zum Erbrechen durchgekaut.

Aber es hilft weder Pluto noch sonst jemand, von etwas anderem als dem "status quo" aus zu erklären.

EDIT: Bezieht sich auf den Beitrag eins weiter oben

creed steiger
Beiträge: 958
Registriert: Mo 11. Sep 2006, 22:56

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von creed steiger »

pluto hat geschrieben:
s[5] nicht auf ein einzelnes Zeichen in deinem String zugreifen konntest,oder?
(bzw das die Length bei Umlauten falsch war)
RICHTIG. Wenn Umalaute/Sonderzeichen im String erhalten sind gibt es bei s[5] was falsches zurück wenn an der 5 Position ein Sonderzeichen ist nd Length gibt auch was Falsches zurück.
Wenn das das einzige Problem ist:
Nochmal ein Beispiel
Dateianhänge
unicode.tar.gz
(95 KiB) 74-mal heruntergeladen

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von mschnell »

theo hat geschrieben:Ich weiss das alles mschnell wir haben das bis zum Erbrechen durchgekaut.
Aber Pluto scheint es nicht verstanden zu habe. deshalb die Wiederholung. Wenn er den "Status quo" nicht versteht, wie soll Pluto dann entscheiden, was er machen soll ? (Die mir bekannten Alternativen habe ich ihm oben erläutert.)
-Michael

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von pluto »

Mit UTF8Strings kannst Du nicht "normal" (d.h. ohne genau zu wissen wie Unicode funktioniert) mit Funktionen wie length, pos, copy oder delete arbeiten. Es gibt keinen Type UTF8Char. Dafür ist nun die Kommunikation mit der LCL einfach.
Wenn diese Aussage richtig ist werde ich mein Projekt komplett auf UTF8String umstellen. Somit kann ich sicher sein das der verwende String Typ UTF8 ist, richtig ?

Ich werde es heute mal austesten.

Viele Dank. Bin erstaunt darüber wie viel ihr über dieses Thema sagen könnt. Warsin. Evtl. sollte jemand von euch einmal ein ausführlich einfaches Tutorial darüber schreiben. Das könnte sehr viele Beiträge sparen....

So wie ich das jetzt verstanden habe ist das Haupt Problem das ich nicht weiß was mein Projekt verwendet. Also nehme ich UTF8String.
Und kann auch auf UTF8 Funktionen und Proceduren zurückgreifen.

@mschnell
Ich Programmiere zwar schon länger(Seit ca 10-12) Jahre und wie Theo schon richtig gesagt habe bin ich auch kein Anfänger mehr,
aber ich habe mich noch nicht so ausführlich mit Strings beschäftigt. Ich weiß wie man sie nutzten und Manipulieren kann. Solange es die guten alten "Standard" Strings sind. Aber sobald es, wie nennt man diesen Bereich eigentlich genau ?
In diesem Thread sind Begriffe wie UTF8String, Widestring, UniCode UTF16 und soweiter gefallen.

Meine Empfehlung für die Zukunft: einer von euch sollte darüber ein ausführliches oder ausreichendes Tutorial schreiben oder eine FAQ Sammlung.
MFG
Michael Springwald

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: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von mse »

pluto hat geschrieben: Meine Empfehlung für die Zukunft: einer von euch sollte darüber ein ausführliches oder ausreichendes Tutorial schreiben oder eine FAQ Sammlung.
Siehe zum Beispiel hier:
http://www.lazarusforum.de/viewtopic.ph ... &sk=t&sd=a

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Re: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von pluto »

Ich habe von einem Tutorial gesprochen nicht von einem Thread mit 111 Beiträgen. Werde ich mir aber Trotzdem anschauen. Am Anfang hatte ich den Thread mit verfolgt jedoch wurde er mir zu unübersichtlich.
MFG
Michael Springwald

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: Erkennen ob das Zeichen ein UTF8 Zeichen ist

Beitrag von mse »

pluto hat geschrieben:Ich habe von einem Tutorial gesprochen nicht von einem Thread mit 111 Beiträgen. Werde ich mir aber Trotzdem anschauen. Am Anfang hatte ich den Thread mit verfolgt jedoch wurde er mir zu unübersichtlich.
Ist es so einfacher? ;-)
string
http://www.freepascal.org/docs-html/ref ... 330003.2.2
Typ zur Speicherung von Text, Implementierung von Compiler-Einstellungen abhängig.

shortstring
http://www.freepascal.org/docs-html/ref ... 340003.2.3
Ein Array von 256 Bytes, das erste Byte bezeichnet die Anzahl gültige Zeichen. Lokale shortstring Variablen belegen Speicher im Stack.

ansistring
http://www.freepascal.org/docs-html/ref ... 350003.2.4
Ein Speicher Block im Heap, Aufbau:

Code: Alles auswählen

 
  TAnsiRec = Packed Record
    Ref,
    Len   : SizeInt;
    First : Char;
  end;
 
Nach First folgen die weiteren 8-Bit Zeichen des String, nach dem letzen Zeichen folgt ein #0.
In einer ansistring Variable wird ein Pointer auf First gespeichert, ein leerer ansistring wird mittels NIL Pointer dargestellt. Bei der Zuweisung eines ansistring an eine ansistring Variable wird der Pointer kopiert und Ref inkrementiert, falls der Pointer nicht NIL ist. Es muss also nicht der gesamte Stringinhalt kopiert werden, was eine wesentlich besserer Leistung ermöglicht.
Verlässt eine ansistring Variable den Sichtbarkeitsbereich, wird Ref dekrementiert falls der Pointer nicht NIL ist. Erreicht Ref Null, wird der Speicherblock freigegeben. Dieser Mechanismus gilt auch für dynamische Arrays.
Wird auf ein Zeichen schreibend zugegriffen (ansistring1[1]:= 'A';), wird zuerst eine Kopie des Speicher Blocks erstellt, falls Ref >1 ist, damit sich die Änderung nicht auf andere "Besitzer" des ursprünglichen Strings auswirken. Dies gilt *nicht* für dynamische Arrays.

widestring
http://www.freepascal.org/docs-html/ref ... 360003.2.5

Unter Linux und anderen Unix-Systemen:
Ein Speicher Block im Heap, Aufbau:

Code: Alles auswählen

 
  TWideRec = Packed Record
    Ref : SizeInt;
    Len : SizeInt;
    First : WideChar;
  end;
 
Die einzelnen Zeichen sind 16Bit statt 8Bit breit, im Übrigen gilt das unter ansistring Gesagte.

Unter Windows:
Ein Speicher Block im Windows OLE-System Speicher, Aufbau:

Code: Alles auswählen

 
  TWideRec = Packed Record
    Len   : DWord;
    First : WideChar;
  end;
 
Hier wird keine Referenzzählung durchgeführt, Kopieroperationen kopieren den kompletten Speicherblock. Dadurch dass kein Heapspeicher verwendet wird, können die OLE-Strings an andere Programme übergeben werden.

pchar
Ein pointer auf einen durch #0 abgeschlossenes 8Bit character array, wird hauptsächlich in der Programmiersprache C benutzt.

pwidechar
Ein pointer auf einen durch #0 abgeschlossenes 16Bit character array, wird hauptsächlich in der Programmiersprache C benutzt.

Zeichencodierung:
In der Komputerei gibt es verschiedene Vereinbarungen, wie die einzelnen Schriftzeichen in Komputerprogrammen dargestellt werden. Beispiele:

ASCII
http://en.wikipedia.org/wiki/ASCII
Benützt einzelne 7Bit Speichereinheiten (#0..#127), kann Steuerzeichen (cariage return, linefeed, form feed...) grosse und kleine lateinische Buchstaben, Ziffern und einige Satz- und Sonderzeichen darstellen, aber keine Umlaute. Zur Speicherung eines ASCII-Zeichens wird in der Regel ein Byte verwendet, das höchstwertige Bit ist dabei immer Null.

Weitere 1 Byte Codierungen verwenden die von ASCII nicht benutzten Werte #128..#255 zur Darstellung regionenspezifischer Zeichen, Beispiele:
ISO 8859-1 (Latin 1)
http://en.wikipedia.org/wiki/ISO-8859-1##ISO-8859-1
koi18-r1
http://en.wikipedia.org/wiki/KOI8-R
ANSI wird öfters als Synonym für die aktuelle Codierung unter Windows oder für Windows-1252 verwendet.
http://en.wikipedia.org/wiki/Windows-1252
Alle diese Codierungen benötigen pro Zeichen ein Byte, durch die Begrenzung auf 256 unterscheidbare Zeichen können in einem String Sonderzeichen verschiedener Regionen nicht gemischt werden.

Unicode ist ein international genormtes Bezeichnungssystem, welches für alle existierenden Schriftzeichen einen "Codepoint" bereitstellt.
http://en.wikipedia.org/wiki/Unicode
http://unicode.org/
Ein Codepoint kann Werte zwischen $00000000 und $0010FFFF besitzen. Zur Darstellung im Komputerspeicher werden verschiedene Formate verwendet:
utf-32, ein Codepoint wird in einen 32bit Wert abgebildet, benötigt 4 Bytes pro Zeichen.
utf-16, ein Codepoint wird in einen oder zwei 16Bit Werte abgebildet, benötigt 2 oder 4 Bytes pro Zeichen.
utf-8, ein Codepoint wird in ein bis vier 8Bit Werte abgebildet, benötigt 1 bis 4 Bytes pro Zeichen.
UCS-2 ist eine Untermenge von utf-16 die einige tote Sprachen und bestimmte Zeichen des traditionellen Chinesisch und weitere selten gebrauchte Zeichen nicht enthält, benötigt 2 Bytes pro Zeichen.

FPC stellt zur Laufzeit verschiedene Automatische Umwandlungen zwischen den verschiedenen Stringtypen bereit.
shortstring ansistring, die Zeichen werden unverändert übernommen.
ansistring -> pchar,
widestring -> pwidechar, falls ansi/widestring = '' (pointer ist NIL) ist, wird ein Pointer auf #0 geliefert, andernfalls der normale Pointer auf First. Dies funktioniert, da ein ansi- oder widestring immer mit einem nachfolgenden #0 abgeschlossen ist.
ansistring -> widestring, der ansistring wird vom widestringmanager unter Verwendung der aktuellen Systemcodierung in utf-16 gewandelt, unter Linux muss dafür die unit cwstring unter uses aufgeführt werden.
widestring -> ansistring, der utf-16 codierte widestring wird vom widestringmanager in die aktuelle Systemcodierung gewandelt, unter Linux muss dafür die unit cwstring unter uses aufgeführt werden. Möglicherweise können nicht alle Zeichen des widestring in der Systemcodierung dargestellt werden.

Lazarus verwendet für Texte utf-8 codierte ansistrings auf allen Systemen, die automatische Wandlung Lazarus ansistring widestring versagt daher dort, wo nicht utf-8 verwendet wird, namentlich unter Windows. Zudem ist zu beachten, dass die Einzelzeichen eines Lazarus ansistring nicht durch Index angesprochen werden können (char1:= ansistring1[1];) da utf-8 Zeichen eine variable Länge von 1 bis 4 Bytes besitzen.

Im Gegensatz dazu verwendet MSEide+MSEgui durchgehend widestrings, automatische Konvertierung ansistring widestring funktioniert und Einzelzeichen können durch Index angesprochen werden, sofern die Codepoints im UCS2 Bereich liegen.

http://sourceforge.net/projects/mseide-msegui

Martin

Antworten