AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Suche nach String mit 'decomposed' Character
Thema durchsuchen
Ansicht
Themen-Optionen

Suche nach String mit 'decomposed' Character

Ein Thema von Maekkelrajter · begonnen am 6. Okt 2024 · letzter Beitrag vom 7. Okt 2024
Antwort Antwort
Seite 1 von 2  1 2      
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
157 Beiträge
 
Delphi 12 Athens
 
#1

Suche nach String mit 'decomposed' Character

  Alt 6. Okt 2024, 12:09
In diesem Thread (Artikel #20) hatte ich bereits das Problem mit unterschiedlich codierten Umlauten thematisiert. Zur Zeit brüte ich über einer Suchfunktion, die in einem TMemo bei einer Suche nach 'Götterdämmerung' sowohl 'Götterdämmerung' (precomposed = Götterdämmerung) als auch 'Götterdämmerung' (decomposed = Götterdämmerung) findet.
Das ist wohl alles andere als trivial, aber es scheint doch möglich zu sein. Das Windows Notepad z. B. findet beide, wenn ich von Hand 'Götterdämmerung' in den Suchdialog eingebe, aber auch wenn ich den Suchstring (in beiden Varianten) per Copy & Paste einfüge.
Ich suche vor allem erstmal überhaupt einen Ansatz.
Wenn ich das Memo mit ANSI füttere, klappt zwar die Suche nach 'Götterdämmerung', aber mit keiner der verfügbaren Codepages werden alle Sonderzeichen korrekt decodiert, also keine Option.
Vielleicht kennt jemand eine Lösung oder auch nur einen Lösungsansatz?

Gruß LP
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.910 Beiträge
 
Delphi 12 Athens
 
#2

AW: Suche nach String mit 'decomposed' Character

  Alt 6. Okt 2024, 12:32
Ich vermute einmal, dass intern auf eine einheitliche Kodierung gewechselt wird. Die Darstellung mit separatem Trema habe ich unter Windows oder Linux z.B. noch nie gesehen.

Das Windows Notepad z. B. findet beide, wenn ich von Hand 'Götterdämmerung' in den Suchdialog eingebe, aber auch wenn ich den Suchstring (in beiden Varianten) per Copy & Paste einfüge.
Wenn ich den Assemblercode richtig deute, wird dort zeilenweise gesucht und dabei wcsncmp bzw. _tcsncmp oder CompareStringW verwendet, je nachdem, ob Groß- und Kleinbuchstaben unterschieden werden oder nicht.

Meine Assemblerkenntnisse reichen nicht aus, um das genauer zu untersuchen. Und das gilt auch nur für die alte Notepad-Version, nicht für die Variante in Windows 11.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Benutzerbild von paule32.jk
paule32.jk

Registriert seit: 24. Sep 2022
Ort: Planet Erde
356 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Suche nach String mit 'decomposed' Character

  Alt 6. Okt 2024, 12:45
vieleicht hilft ja die Delphi-Komponente TSynEdit weiter ?
diese kommt mit Unicode und Such-Komponenten.

außerdem kann TSynEdit mit größeren Dateien etwas mehr anfangen als TMemo.
soweit ich mich erinnern kann, reicht TMemo das Limit von 64k Texten, weshalb
ich in früheren Tagen meiner Programmiererei TRichEdit verwendet hatte.
TRichEdit kann mehr als 64k Daten sammeln - und auch colorieren.

Aber wie geschrieben: TSynEdit kann das auch - vieleicht ein wenig besser.
Zudem müsste TSynEdit OpenSource und frei verwendbar sein...
Frag doch einfach
Alles was nicht programmiert werden kann, wird gelötet
  Mit Zitat antworten Zitat
mmw
(Gast)

n/a Beiträge
 
#4

AW: Suche nach String mit 'decomposed' Character

  Alt 6. Okt 2024, 13:55
Hallo,

hier wäre noch eine kostenlose Memo Komponente (näheres dazu auf der Website, scheint damit zu funktionieren).

http://www.ecmqc.com/plusmemo/pmHome.htm


Bei der Installation in Delphi 12 sollte es reichen die '*.inc' -Datei entsprechend anzupassen.

Gruß

Geändert von mmw ( 6. Okt 2024 um 14:27 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Gausi
Gausi

Registriert seit: 17. Jul 2005
901 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Suche nach String mit 'decomposed' Character

  Alt 6. Okt 2024, 14:21
Das Windows Notepad z. B. findet beide, wenn ich von Hand 'Götterdämmerung' in den Suchdialog eingebe, aber auch wenn ich den Suchstring (in beiden Varianten) per Copy & Paste einfüge.
Ich kann zwar nichts zur Lösung beitragen, aber wenn ich die Götterdämmerung in den unterschiedlichen Kodierungen in eine Textdatei einfüge, die der Windows-11-Editor wohl als UTF8 ohne BOM speichert, dann findet die Suchfunktion sowohl vom Windows-11-Editor als auch die von Notepad++ nicht beide Varianten, sondern in beiden Fällen nur eine - eben die, die gesucht wurde.

Dass die Kodierung beim Copy&Paste nicht kaputt gegangen ist, kann man in einem HexEditor sehen.
Being smart will count for nothing if you don't make the world better. You have to use your smarts to count for something, to serve life, not death.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.339 Beiträge
 
Delphi 12 Athens
 
#6

AW: Suche nach String mit 'decomposed' Character

  Alt 6. Okt 2024, 14:34
Es kommt auch drauf an, wie gesucht wird.

Es gibt Stringvergleichsfunktionen, die behandeln auch unterschiedliche Composings.
RegEx tut sowas z.B. nicht und vergleicht nur binär.

Man kann beim Suchen vorher auf den Text und den Suchtext je einmal normalisieren und anschließend vergleichen.



PS:
Delphi und UTF-8 : Nach Umlauten suchen geht nur, wenn die Datei/Unit im Editor bereits geladen ist,
weil dort im Unicode-Buffer des Editors gesucht wird, während die Suchfunktion für direkten Dateizugriff einfach nur bähhhhh ist und Emba das seit vielen Jahren nicht reparieren will. (UTF-8 wird da einfach als blind "ANSI" geladen)
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu ( 6. Okt 2024 um 14:40 Uhr)
  Mit Zitat antworten Zitat
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
157 Beiträge
 
Delphi 12 Athens
 
#7

AW: Suche nach String mit 'decomposed' Character

  Alt 6. Okt 2024, 15:10
Ich kann zwar nichts zur Lösung beitragen, aber wenn ich die Götterdämmerung in den unterschiedlichen Kodierungen in eine Textdatei einfüge, die der Windows-11-Editor wohl als UTF8 ohne BOM speichert, dann findet die Suchfunktion sowohl vom Windows-11-Editor als auch die von Notepad++ nicht beide Varianten, sondern in beiden Fällen nur eine - eben die, die gesucht wurde.
Dass die Kodierung beim Copy&Paste nicht kaputt gegangen ist, kann man in einem HexEditor sehen.
Mein 'Versuchsaufbau':
Eine Stringlist, die beide Codierungsvarianten enthält, wird als 'Unicode' mit BOM gespeichert:
Delphi-Quellcode:
FN := 'content_06-10-2024_15-41.txt'
MyStringlist.SaveToFile(FN,TEncoding.unicode)
Kontrolle mit einem Hexeditor zeigt, dass beide Codierungen in der Datei vorkommen.
Anschließend wird diese Datei mit dem Notepad geöffnet. Notepad erkennt 'UTF-16 LE'
Beide Varianten werden gefunden, wenn ich von Hand 'Götterdämmerung' in den Suchdialog eingebe, aber auch wenn ich den Suchstring (in beiden Varianten) per Copy & Paste einfüge (gerade nochmal ausprobiert).
Mein OS ist allerdings Windows 10.
Edit:
Hier (Artikel #4) ist eine Datei zu finden, die beide Codierungsvarianten enthält: 'MacOS_ItunesContent.txt'

Gruß LP

Geändert von Maekkelrajter ( 6. Okt 2024 um 15:33 Uhr)
  Mit Zitat antworten Zitat
Maekkelrajter

Registriert seit: 8. Mär 2017
Ort: Köln
157 Beiträge
 
Delphi 12 Athens
 
#8

AW: Suche nach String mit 'decomposed' Character

  Alt 6. Okt 2024, 21:59
Hallo, hier wäre noch eine kostenlose Memo Komponente (näheres dazu auf der Website, scheint damit zu funktionieren).
Hier gibt es eine Demo, mit der es leider auch nicht funktioniert
Es handelt sich zwar um die Version 6.6a (2011), aber auch aus dem Changelog bis V 7.2 (2018) läßt sich nicht entnehmen, dass eine der Änderungen das behoben hätte.
Schade, eine Hoffnung weniger!

Gruß LP
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.910 Beiträge
 
Delphi 12 Athens
 
#9

AW: Suche nach String mit 'decomposed' Character

  Alt 6. Okt 2024, 22:51
Ich halte das eher für einen Bug bei der Zeichenkodierung. Ich kenne keine korrekte Möglichkeit, in der 6F 00 08 03 für ein ö steht. Das ist weder UTF-8 noch UTF-16. Das wird offenbar trotzdem richtig gelesen, aber ich verstehe nicht warum.

// EDIT:
08 03 steht für Trema.
Sebastian Jänicke
AppCentral

Geändert von jaenicke ( 7. Okt 2024 um 06:01 Uhr)
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
390 Beiträge
 
#10

AW: Suche nach String mit 'decomposed' Character

  Alt 7. Okt 2024, 09:16
Hi,

In diesem Thread (Artikel #20) hatte ich bereits das Problem mit unterschiedlich codierten Umlauten thematisiert. Zur Zeit brüte ich über einer Suchfunktion, die in einem TMemo bei einer Suche nach 'Götterdämmerung' sowohl 'Götterdämmerung' (precomposed = Götterdämmerung) als auch 'Götterdämmerung' (decomposed = Götterdämmerung) findet.
Das ist wohl alles andere als trivial,
To be honest it is trivial ! but with the right tools.

Which is completely different APIs like FindNLSString and FindNLSStringEx
https://learn.microsoft.com/en-us/wi...-findnlsstring
https://learn.microsoft.com/en-us/wi...indnlsstringex
in fact all the functions the following link capable to perform what you want, with more or less tweaking parameters
https://learn.microsoft.com/en-us/wi...port-functions

Windows has National Language Support (NLS) and International Components for Unicode (ICU), but there is differences, ICU introduced to Windows 10 Creator, while NLS was there since Windows Vista (at least i think)

Anyway here is a simple test for you search problem and its solution, i will paste the code and attach the project because i can't trust the browsers to keep encoding right.

Delphi-Quellcode:
unit Unit11;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.StdCtrls;

type
  TForm11 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    procedure SearchStringList(AList: TStringList);
    procedure SearchStringFindNLSString(AList: TStringList);
    procedure SearchStringFindNLSStringEx(const LOCALE_NAME: string; AList: TStringList);
  end;

var
  Form11: TForm11;

implementation

{$R *.dfm}

const
  SUB_STR_1 = 'Götterdämmerung';
  SUB_STR_2 = 'Götterdämmerung';

procedure TForm11.FormCreate(Sender: TObject);
begin
  Button1.Click;
end;

procedure TForm11.SearchStringFindNLSString(AList: TStringList);

  procedure DoFindWithFindNLSString(const SubStr: string);
  var
    i, Res, Found: Integer;
  begin
    for i := 0 to AList.Count - 1 do
    begin // LOCALE_USER_DEFAULT = $400
      Res := FindNLSString(LOCALE_USER_DEFAULT, FIND_FROMSTART, PChar(AList.Strings[i]), -1, PChar(SubStr), -1, @Found);
      if (Res <> -1) and (Found > 0) then
        Memo1.Lines.Add(IntToStr(i));
    end;
  end;

begin
  Memo1.Lines.Add('finding lines with SUB_STR_1 = ' + SUB_STR_1);
  DoFindWithFindNLSString(SUB_STR_1);

  Memo1.Lines.Add('finding lines with SUB_STR_2 = ' + SUB_STR_2);
  DoFindWithFindNLSString(SUB_STR_2);
end;

procedure TForm11.SearchStringFindNLSStringEx(const LOCALE_NAME: string; AList: TStringList);

  procedure DoFindWithFindNLSStringEx(const SubStr: string);
  var
    i, Res, Found: Integer;
  begin
    for i := 0 to AList.Count - 1 do
    begin
      Res := FindNLSStringEx(PChar(LOCALE_NAME), FIND_FROMSTART, PChar(AList.Strings[i]), -1, PChar(SubStr), -1, @Found, nil, nil, 0);
      if (Res <> -1) and (Found > 0) then
        Memo1.Lines.Add(IntToStr(i));
    end;
  end;

var
  i, Res, Found: Integer;
begin
  Memo1.Lines.Add('finding lines with SUB_STR_1 = ' + SUB_STR_1);
  DoFindWithFindNLSStringEx(SUB_STR_1);

  Memo1.Lines.Add('finding lines with SUB_STR_2 = ' + SUB_STR_2);
  DoFindWithFindNLSStringEx(SUB_STR_2);
end;

procedure TForm11.SearchStringList(AList: TStringList);

  procedure DoFindWithPos(const SubStr: string);
  var
    i: Integer;
  begin
    for i := 0 to AList.Count - 1 do
      if Pos(SubStr, AList.Strings[i]) > 0 then
        Memo1.Lines.Add(IntToStr(i));
  end;

begin
  Memo1.Lines.Add('finding lines with SUB_STR_1 = ' + SUB_STR_1);
  DoFindWithPos(SUB_STR_1);

  Memo1.Lines.Add('finding lines with SUB_STR_2 = ' + SUB_STR_2);
  DoFindWithPos(SUB_STR_2);
end;

procedure TForm11.Button1Click(Sender: TObject);
var
  sList: TStringList;
  i: Integer;
begin
  sList := TStringList.Create;
  try
    sList.LoadFromFile('MacOS_ItunesContent_Small.txt');
    if sList.Count = 0 then
      Exit;
    for i := 0 to sList.Count - 1 do
      Memo2.Lines.Add(IntToStr(i) + #9 + sList.Strings[i]);

    Memo1.Lines.Add('Searching using Pos');
    SearchStringList(sList);
    Memo1.Lines.Add(#13#10'Searching with FindNLSString');
    SearchStringFindNLSString(sList);
    Memo1.Lines.Add(#13#10'Searching with FindNLSStringEx and LOCALNAME=''''');
    SearchStringFindNLSStringEx('', sList);

  finally
    sList.Free;
  end;
end;

end.
The data file in question, which is minimized and edited a little is MacOS_ItunesContent_Small.txt
Zitat:
dummy line

Götterdämmerung
Götterdämmerung
Track 4344
Track ID: 11572
Titel: Morgendämmerung und Siegfried's Rheinfahrt aus "Götterdämmerung"
Artist: Richard Wagner
Album: Rheingold
Track-Art: Abgeglichene AAC-Audiodatei
GUID:
Hinzugefügt: 14.12.2017 17:57:46
Persistent ID: 91453A3B4084EC74
Tracktype: File
Speicherort: Macintosh HD/Users/AlfonsYondraschek/Music/iTunes 1/iTunes Media/Music/Richard Wagner/Rheingold/05 Morgendämmerung und Siegfried's Rheinfahrt aus _Götterdämmerung_.m4a

Track 4345
Track ID: 11574
Titel: Siegfried's Trauermarsch und Finale aus "Götterdämmerung"
Artist: Richard Wagner
Album: Rheingold
Track-Art: Abgeglichene AAC-Audiodatei
GUID:
Hinzugefügt: 14.12.2017 17:57:46
Persistent ID: 6C45FF4271B8A57B
Tracktype: File
Speicherort: Macintosh HD/Users/AlfonsYondraschek/Music/iTunes 1/iTunes Media/Music/Richard Wagner/Rheingold/06 Siegfried's Trauermarsch und Finale aus _Götterdämmerung_.m4a
The result should be like this
Zitat:
Searching using Pos
finding lines with SUB_STR_1 = Götterdämmerung
2
6
18
finding lines with SUB_STR_2 = Götterdämmerung
3
14
26

Searching with FindNLSString
finding lines with SUB_STR_1 = Götterdämmerung
2
3
6
14
18
26
finding lines with SUB_STR_2 = Götterdämmerung
2
3
6
14
18
26
And here screenshot of the result for any cases
2024-10-07 11_02_02-Untitled.png

The project with the data file
FindNLSString.zip

Notes on FindNLSString and FindNLSStringEx:
1) Although the documentation of FindNLSString advice to move to FindNLSStringEx, yet Notpad.exe is using FindNLSString !
2) FindNLSStringEx use LOCALE_NAME (plain string) instead of the structured LOCALE_NAME value, yet it is go complicated very fast when you need to chain many languages, so the sticking to default (USER or SYSTEM) is easier, in that case it is better and easier to use FindNLSString.
3) implementing similar algorithm in pure Pascal is huge job unless you will depend on either NLS or the ICU library, well .. such dependency will render any implementation useless and waste of time.

Hope that help
Kas
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:53 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