Stringirrsinn - Unicode, UTF8, Widestring,....

Für Fragen von Einsteigern und Programmieranfängern...
Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6216
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von af0815 »

Ich glaube die Lösung von Theo ist für mich die richtige.

Besonders das hier

Code: Alles auswählen

//Mit Case "Buchstaben" ersetzen
   for i:=1 to s.length do
    case s[i] of
      'o','ö': s[i]:='@';
    end;
 


BTW: Wie geht das Beispiel (und die anderen von Theo) eigentlich mit den aktuellen 'irgendwas'-Strings ?
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

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

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von theo »

af0815 hat geschrieben:BTW: Wie geht das Beispiel (und die anderen von Theo) eigentlich mit den aktuellen 'irgendwas'-Strings ?


Laut wp_xyz hat sich bzgl. UTF8 Char "Handling" nichts vereinfacht. K.A.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von Michl »

af0815 hat geschrieben:Ich glaube die Lösung von Theo ist für mich die richtige.
Ja, das würde vermutlich das Arbeiten mit Strings sehr erleichtern. Und diverse Fragen in den Foren nicht aufkommen lassen.


af0815 hat geschrieben:Besonders das hier

Code: Alles auswählen

//Mit Case "Buchstaben" ersetzen
   for i:=1 to s.length do
    case s[i] of
      'o','ö': s[i]:='@';
    end;
 

BTW: Wie geht das Beispiel (und die anderen von Theo) eigentlich mit den aktuellen 'irgendwas'-Strings ?

Ich glaube zwar, die Frage ist eher rhetorisch, dass es ähnlich funktionieren kann, habe ich eben getestet:

Code: Alles auswählen

uses ..., LazUTF8;
 
procedure TForm1.Button1Click(Sender: TObject);
var
  s: String;
  i: Integer;
begin
  s := 'Möchte Möhre ohne ö';
  for i := 1 to UTF8Length(s) do
    case UTF8Copy(s, i, 1) of
      'o', 'ö':
        begin
          UTF8Delete(s, i, 1);
          UTF8Insert('@', s, i);
        end;
    end;
  Caption := s;
end;

Nur zur Klarstellung, ich will nicht den Weg von FPC verfechten, halte es aber anders herum nicht für klug die neuen Strings zu verteufeln. Lazarus stellt mit LazUTF8 ein paar nützliche Methoden im Umgang mit UTF8 kodierten Strings zur Verfügung, da Lazarus selbst zur Zeit voll auf UTF8 kodierte Strings baut.

@theo: hast du denn mal probiert deinen Code bei FPC oder Lazarus zu bewerben und ihnen zur Verfügung zu stellen? Ich fände es auf jeden Fall eine Bereicherung!!!

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

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

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von theo »

@Michl: Klar geht das irgendwie.
Die Frage war aber wahrscheinlich, ob das mit Bordmitteln jetzt elegant, performant und ohne Kopfzerbrechen geht.
Und wenn niemand eine bessere Lösung hat, muss man das wohl verneinen.

Das Problem bei diesen Fkt. ist, dass sie kein Gedächtnis haben.
Die Positionen müssen immer wieder vom String Anfang her gesucht werden, bei jedem einzelnen Funktionsaufruf!
TUniString springt nur immer zum nächsten Codepoint.
Außerdem ersetzt TUniString tatsächlich wenn möglich nur die entsprechenden Bytes und macht kein aufwändiges Löschen und Einfügen.

Michl hat geschrieben:@theo: hast du denn mal probiert deinen Code bei FPC oder Lazarus zu bewerben und ihnen zur Verfügung zu stellen? Ich fände es auf jeden Fall eine Bereicherung!!!

Nein, das habe ich nicht.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von Michl »

theo hat geschrieben:@Michl: Klar geht das irgendwie.
Die Frage war aber wahrscheinlich, ob das mit Bordmitteln jetzt elegant, performant und ohne Kopfzerbrechen geht.
Und wenn niemand eine bessere Lösung hat, muss man das wohl verneinen.

Das Problem bei diesen Fkt. ist, dass sie kein Gedächtnis haben.
Die Positionen müssen immer wieder vom String Anfang her gesucht werden, bei jedem einzelnen Funktionsaufruf!
TUniString springt nur immer zum nächsten Codepoint.
Außerdem ersetzt TUniString tatsächlich wenn möglich nur die entsprechenden Bytes und macht kein aufwändiges Löschen und Einfügen.

Michl hat geschrieben:@theo: hast du denn mal probiert deinen Code bei FPC oder Lazarus zu bewerben und ihnen zur Verfügung zu stellen? Ich fände es auf jeden Fall eine Bereicherung!!!

Nein, das habe ich nicht.

Das klingt doch sehr gut!!! Möchtest du deinen Code Lazarus zur Verfügung stellen oder siehst du eher keinen Bedarf? Ich meine die Entwickler von Lazarus scheinen mir sehr offen für neue gute Ansätze, besonders wenn sie mit dem aktuellen FPC umsetzbar sind.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

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

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von theo »

Michl hat geschrieben:Das klingt doch sehr gut!!! Möchtest du deinen Code Lazarus zur Verfügung stellen oder siehst du eher keinen Bedarf? Ich meine die Entwickler von Lazarus scheinen mir sehr offen für neue gute Ansätze, besonders wenn sie mit dem aktuellen FPC umsetzbar sind.


Dieser Code steht ja schon seit Jahren zur Verfügung.
Bis jetzt hat niemand von den Lazarus Entwicklern danach gefragt.

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: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von mschnell »

theo hat geschrieben:Bis jetzt hat niemand von den Lazarus Entwicklern danach gefragt.


Ich habe ja auch versucht, da etwas anzustoßen, aber die propagieren die Delphi-XE voll-Kompatibilität (statt einer "abwärts"-Kompatibilität die die internen Mechanismen ändert, aber Delphi Code trotzdem in nahezu 100% der Fälle ohne Änderung portieren kann).

Und da ist eben kein Platz für alternative Ansätze, sei es nun im internen Ablauf, oder in den Empfehlungen wie die User programmieren sollen .

-Michael

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

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von theo »

mschnell hat geschrieben:
theo hat geschrieben:Bis jetzt hat niemand von den Lazarus Entwicklern danach gefragt.


Ich habe ja auch versucht, da etwas anzustoßen, aber die propagieren die Delphi-XE voll-Kompatibilität (statt einer "abwärts"-Kompatibilität die die internen Mechanismen ändert, aber Delphi Code trotzdem in nahezu 100% der Fälle ohne Änderung portieren kann).

Und da ist eben kein Platz für alternative Ansätze, sei es nun im internen Ablauf, oder in den Empfehlungen wie die User programmieren sollen .


Ja, ist schon klar, dass TUniString für FPC/Lazarus nicht der Königsweg sein kann.
Ich habe das deshalb auch nicht aktiver "gepusht", auch weil ich ellenlange Unicode Diskussionen leid bin.
TUniString ist - soweit mir bekannt - für das "UTF8-Char-Handling" wahrscheinlich im Moment die praktischste und performanteste "Notlösung".

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von Michl »

Habe eben nochmal darüber nachgedacht. So geht es aktuell auch umzusetzen (eben getestet):

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
var
  s: String;
  i: Integer;
begin
  s := 'Möchte Möhre ohne ö';
  for i := 1 to s.Length do
    case s.Chars[i] of
      'o', 'ö': s.Chars[i] := '@';
    end;
  Caption := s;
end;

bei

Code: Alles auswählen

{$modeswitch typehelpers}  
...
type
  TStringHelper = type helper for string
  private
    function GetChars(Index: Integer): TUTF8Char;
    procedure PutChars(Index: Integer; aUTF8Char: TUTF8Char);
    function GetLength: Integer;
  public
    property Chars[Index: Integer]: TUTF8Char read GetChars write PutChars;
    property Length: Integer read GetLength;
  end;
 
...
 
function TStringHelper.GetLength: Integer;
begin
  Result := UTF8Length(Self);
end;
 
function TStringHelper.GetChars(Index: Integer): TUTF8Char;
begin
  Result := UTF8Copy(Self, Index, 1);
end;
 
procedure TStringHelper.PutChars(Index: Integer;
  aUTF8Char: TUTF8Char);
begin
  UTF8Delete(Self, Index, 1);
  UTF8Insert(aUTF8Char, Self, Index);
end;
 


Angelehnt an https://theroadtodelphi.wordpress.com/2012/09/05/exploring-delphi-xe3-record-helpers-for-simple-types-system-sysutils-tstringhelper/.

Natürlich performanter ist die Lösung auch nicht.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

wp_xyz
Beiträge: 4893
Registriert: Fr 8. Apr 2011, 09:01

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von wp_xyz »

Ich glaube, das gibt es das Problem, dass Index irgendwas sein kann, das ganze aber nur funktioniert, wenn Index zum Beginn eines Zeichens zeigt.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von Michl »

Tut es doch. Es werden doch die UTF8-Methoden verwendet. Oder ich verstehe dich falsch.

Deswegen funktioniert es auch mit zum Aufwärtszählen des Indexes, obwohl ein 2Byte Char durch einen 1Byte Char ersetzt wird (s.Length ist nicht gleich Length(s) in diesem Beispiel!!!).

[Edit] Wahrscheinlich sollte man dann auch andere Bezeichner z.B. s.Count wählen, um derartige Missverständnisse zu vermeiden...

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

wp_xyz
Beiträge: 4893
Registriert: Fr 8. Apr 2011, 09:01

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von wp_xyz »

Ist schon ok - da war ich mal wieder auf der langen Leitung.

Jokra
Beiträge: 8
Registriert: So 17. Apr 2022, 16:23
OS, Lazarus, FPC: Win10, WinXP (Lazarus 2.2.0)
CPU-Target: 64 Bit, (32 Bit)
Wohnort: 30952 Ronnenberg

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von Jokra »

Also, die Überschrift dieses Threads trifft den Nagel auf den Kopf. Obwohl ich mit Programmieren angefangen habe (1966), als die meisten der Leser und Schreiber dieses Forums noch lange irgendwo im Käseregal gelegen haben, bin ich eigentlich noch Lazarus-Neuling (mit Ausnahme eines kurzen Intermezzos ca. 2002.) Der Grund, dass ich mich überhaupt hierher begeben musste, ist, dass weder mein bevorzugtes Delphi 5.5 (!) noch ein neueres von Embarcadero mit .tif-Bildern umgehen konnten.

Letzteres funktioniert mit Lazarus sehr gut - eine Funktion zur Rückkodierung von .bmp nach .tif wäre das Nonplusultra, aber nicht lebensnotwendig. Auch das Auswählen, Einlesen und Laden von Bilddateien geht problemlos. Nur wenn im Filenamen ein Umlaut auftaucht, ist Ende Gelände. Inzwischen kenne ich mich bestens aus, was UTF-x, Unicode, die CPs 1252, 8859-1 und -15 und ein CodePoint sind. An und für sich wäre es ja ein Klacks, z.B. den total vermurksten Filenamen "1091-Z'#$FC'rich.tif" wieder zu korrigieren, so dass Windows das File auch findet, aber die Codierung ist so vernagelt, dass man mit Bordmitteln (Stringoperationen) gegen eine Granitwand läuft. Alles deutet darauf hin, dass das "Vernageln" in dem Moment passiert, in dem der richtige Filename nach seiner Nummer identifiziert, aus der Stringliste in einen Eizelstring zum Laden übernommen wird, denn die Stringliste mit den verfügbaren Files bleibt auch nach LoadFromFile und sogar nach SaveToFile unverändert.

Ich habe den Eindruck, dass aus lauter blinder Unicode- und UTF-8-Begeísterung, die ja in einem entsprechenden Problemfeld nicht unberechtigt sein mögen, die Fileoperationen vergessen worden sind, die natürlich nicht mehr funktionieren können, wenn unnötigerweise an der System-Codepage herumgemurkst wird. Ich hatte gehofft, dass der Typ TFilename dagegen immun ist, was ja naheliegend wäre, aber das ist nur ein anderer Name für einen stinknormalen String. Inzwischen scheint sogar Windows selbst in UTF-8 herumzumurksen, denn einige meiner Uralt-Delphi-5.5-Programme (z.B. für BackUps und Filelisten) kommen ebenfalls ins Husten, wenn Umlaute auftreten. Das ist auch kein Wunder, denn Windows wird ja regelmäßig up-gedated (verschlimmbessert) und das alte Delphi benutzt viele Windows-API-Funktionen.

Ein Byte-Array habe ich noch nicht versucht. Klingt erst einmal nicht schlecht, aber angesichts des totalen Chaos von nicht funktionierenden Lösungsvorschlägen *), auch wegen des unübersichtlichen Versions-Wirrwars, war mir bisher der Aufwand zu schade. Ausserdem ist mir noch ein Rätsel, wie man überhaupt von einem korrekten Byte-Array wieder zu einem funktionierenden Filenamen kommen soll, denn es ist zu befürchten, dass schon beim Typecast der große Murkser wieder zuschlägt.

Inzwischen habe ich die Suche nach einer Lösung aus lauter Verzweiflung aufgegeben und schreibe jetzt in der Fileliste "Zuerich" - furchtbar !

*) z.B. -dDisableUTF8RTL gem. https://wiki.freepascal.org/Lazarus_wit ... UTF-8_mode

wp_xyz
Beiträge: 4893
Registriert: Fr 8. Apr 2011, 09:01

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von wp_xyz »

Da beigefügte Beispiel-Projekt lädt das Bild mit der Lazarus-Tatze in ein TImage und speichert es unter dem Namen ''äöüαβγ.bmp" ab. Ich bin auf Windows, und die Datei erscheint genauso im Explorer. Also wo ist das Problem?

Statt zu jammern. solltest du genaue Angaben machen, was du tust. Arbeitest du an einem GUI-Programm oder einem Konsolen-Programm? Verwendest du evtl uralte Delphi-5.5 Quelltext, die ANSI-codiert sind? Hast du irgendwelche Grundeinstellungen verändert (-dDisableUTF8RTL - ich weiß gar nicht, ob das heute noch gebraucht wird, aber mit solchen Anweisungen holt man sich die Probleme...)
Dateianhänge
picture_filename_umlaut.zip
(18.35 KiB) 39-mal heruntergeladen

Jokra
Beiträge: 8
Registriert: So 17. Apr 2022, 16:23
OS, Lazarus, FPC: Win10, WinXP (Lazarus 2.2.0)
CPU-Target: 64 Bit, (32 Bit)
Wohnort: 30952 Ronnenberg

Re: Stringirrsinn - Unicode, UTF8, Widestring,....

Beitrag von Jokra »

Liebe*r wp_xyz,
ich bin erst jetzt zufällig über Google mal wieder in dieses Forum hineingestolpert, denn wie ich schon im Beitrag vom 17.12.23 angedeutet habe, habe ich die Hoffnung und die Beschäftigung mit Lazarus und dem damit verbundenen Chaos aufgegeben. Aber erst einmal danke für Deine Antwort, die ich deshalb erst heute gesehen habe. Auch Dein Beitrag vom 18.1.2016 wie auch weitere und die von Michl nützen mir überhaupt nichts ohne eine verlässliche Qelle für ein aktuelles Lazarus *) mit dem das garantiert funktioniert bzw. eine Liste der notwendigen Komponenten und Compilersettings. Ich habe nämlich davon keine Ahnung und will sie eigentlich auch nicht erwerben; ich habe Lazarus ca. Mitte 2022 heruntergeladen und seitdem nichts dran verändert. Ich habe zwar mal etwas von RC1 gelesen, aber keine Ahnung wie und was ich damit machen sollte und könnte.

An sich kann ich mir Fälle, in denen es gut wäre, wenn die ganze Welt und alle Compiler Unicode und möglichst auch noch UTF-8 verwenden würden, gut vorstellen. Da die Welt aber bekanntlich vom Optimum weit entfernt ist, darf niemand, der auch nur einen Hauch von Intelligenz besitzt, fest davon ausgehen. Das scheint aber z.B. bei den Lazarus-Entwicklern und anderen der Fall zu sein. Es scheint leider so zu sein, dass der Herr Windows und der Herr Lazarus davon ausgehen, dass der jeweils andere sich nach der Nase des Gegenübers richtet - was mitnichten der Fall ist !

Meine Forderung ist: Ein Programm darf unter keinen Umständen die vorhandene Codierung verändern und dann auch noch sämtliche Workarounds vernageln wie Lazarus (z.B. ein Typ TFilenamen, garantiert ohnne Umcodierung), es sei denn, es kann das laufende Betriebssystem dazu bringen, die andere (dessen) Codierung richtig zu verarbeiten.

In dem Sinne ist Dein kleines Beispiel am Ende genau das, was ich nicht möchte, denn es macht nichts weiter, als einen Filenamen in einer Windows-fremden (UTF-8) Codierung zu schreiben, was Windows klaglos akzeptiert, und der dann ebenso klaglos wieder eingelesen werden kann. Das könnte ich natürlich problemlos auch machen: einfach durch Lazarus meine Fileliste in UTF-8 neu abspeichern und alles gut ? - nein ! Da stände im Win-Explorer dann "1091-Z'#$FC'rich.tif" statt "1091-Zürich.tif". Das ist ja noch schlimmer als "1091-Zuerich.tif" !
Gruß JK

*) ich arbeite nur mit dem GUI, der Quelltext ist nagelneu, mit Lazarus geschrieben und getestet. Wie gesagt, das Programm ist nicht so ganz trivial, aber funktioniert bis auf die Umlaute bestens.

Antworten