Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - 2 Ansizeichen in ein Sonderzeichen konvertieren


tastenkleber - Do 05.11.15 14:42
Titel: 2 Ansizeichen in ein Sonderzeichen konvertieren
Ich habe diverse Daten aus einer lokalen Datenbank (SQLite3) ausgelesen, wobei viele Strings übersäht sind mit Sonderzeichen.
Z.B.: É -> É oder é -> é oder ü -> ü ... usw.
Um diese Sonderzeichen in ihre Entsprechungen zu konvertieren, habe ich eine kleine Function geschrieben - s.u. Im Grunde genommen habe ich also eine Lösung dafür gefunden.
Aber ich werde das Gefühl nicht los, dass es hierfür auch einfachere Lösungen gibt.
Dazu wüsste ich gern, um welche Sonderzeichen es sich handelt (wie nennt man sie?).
Bei Wikipedia habe ich mich erstmal belehren lassen über ASCII, ANSI, UTF8, Unicode ...
Sehr lehrreich - hat mir aber nicht weitergeholfen bzw. wusste ich schon!
Die Kombinationen habe ich mir dann mühsam aus einer Ansi-Tabelle gesucht.
Hier meine Function (nicht ganz vollständig):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
function osz(s:unicodestring):utf8string;//egal, ob unicodestring, string,utf8string ...
begin
       s:=utf8encode(s); // braucht man nicht unbedingt - geht auch ohne!

       s:= ReplaceStr(s,#195+#159,'ß');
       s:= Replacestr(s,#195+#161,'á');
       s:= Replacestr(s,#195+#160,'à');
       s:= Replacestr(s,#195+#169,'é');
       s:= Replacestr(s,#195+#168,'è');
       s:= Replacestr(s,#195+#179,'ó');
       s:= Replacestr(s,#195+#137,'É');
       s:= Replacestr(s,#195+#154,'Ú');
       s:= Replacestr(s,#195+#173,'í');
       s:= Replacestr(s,#195+#189,'ý');
       s:= Replacestr(s,#195+#184,'ø');
       s:= Replacestr(s,#195+#129,'Á');
       s:= Replacestr(s,#195+#145,'Ñ');
       s:= ReplaceStr(s,#195+#164,'ä');
       s:= ReplaceStr(s,#195+#182,'ö');
       s:= ReplaceStr(s,#195+#188,'ü');
       s:= ReplaceStr(s,#195+#132,'Ä');
       s:= ReplaceStr(s,#195+#150,'Ö');
       s:= Replacestr(s,#195+#156,'Ü');
       s:= Replacestr(s,#276,'Ä');
       s:= Replacestr(s,#294,'Ö');
       s:= Replacestr(s,#207,'Ü');
    //   s:= Replacestr(s,#302,'Ü'); // hä?
       s:= Replacestr(s,#308,'ä');
       s:= Replacestr(s,#326,'ö');
       s:= Replacestr(s,#332,'ü');
       s:= Replacestr(s,#10#13,''); // kein Zeilenumbruch

 result :=s;
end;



PS: ich verwende Delphi XE6
Bei http://docwiki.embarcadero.com/RADStudio/Seattle/de/UTF-8-Konvertierungsroutinen habe ich verschiedene Functionen ausprobiert. Das war leider vergebens.
Falls es hierfür keine einfachere Lösung gibt, verwende ich eben meine eigene function - geht ja schließlich!
Sie kann auch noch verfeinert werden. So ist z.B. der Abstand zwischen 'ä' und 'Ä' oder 'ü' und 'Ü' ... usw stets 32.
Bevor ich in dieser Richtung weitermache, würde ich gern wissen, ob sich diese Mühe überhaupt lohnt!?

Ich hoffe, dass ich mein Problem verständlich geschildert habe und danke im Voraus für Eure Hilfe.

Grüße Jörg


Nersgatt - Do 05.11.15 14:49

Ich glaube, Du zäumst das Pferd von der falschen Seite auf.
Normalerweise kann man in den Datenbankzugriffskomponenten für den Zugriff auf Deine DB einstellen, welches Encoding verwendet wird. Wenn das richtig eingstellt ist, bekommst Du die Daten auch gleich korrekt und musst nicht hinterher korrigieren.


tastenkleber - Do 05.11.15 15:38

@Nersgatt

Das ist zwar richtig! Aber ich habe in der Vergangenheit auch viele solcher Zeichen-Kombinationen in reinen Texten vorliegen gehabt - und da konnte ich keine Encodings einstellen. Und wenn ich z.B. das Netradio-Example aus der Bass-Komponente nehme, dann liefert der String, der die Titelanzeige darstellt, ebenfalls mitunter solche Zeichen-Kombinationen.


ub60 - Do 05.11.15 20:00

In Lazarus gibt es eine Unit lazUTF8.pas, da stehen Unmengen Konvertierungsroutinen drin, so z.B.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function UnicodeToUTF8(CodePoint: cardinal): string;
function UTF8ToSys(const s: string): stringoverload{$IFDEF EnableUTF8RTL}inline;{$ENDIF}
function UTF8ToSys(const AFormatSettings: TFormatSettings): TFormatSettings; overload{$IFDEF EnableUTF8RTL}inline;{$ENDIF}
function SysToUTF8(const s: string): stringoverload;
function SysToUTF8(const AFormatSettings: TFormatSettings): TFormatSettings; overload;
function ConsoleToUTF8(const s: string): string;// converts OEM encoded string to UTF8 (used with some Windows specific functions)
function UTF8ToConsole(const s: string): string;// converts UTF8 string to console encoding (used by Write, WriteLn)
function UnicodeToUTF8(CodePoint: cardinal; Buf: PChar): integer;
function UnicodeToUTF8SkipErrors(CodePoint: cardinal; Buf: PChar): integer;
function UnicodeToUTF8Inline(CodePoint: cardinal; Buf: PChar): integer; inline;
function UTF8ToDoubleByteString(const s: string): string;
function UTF8ToDoubleByte(UTF8Str: PChar; Len: PtrInt; DBStr: PByte): PtrInt;

... und viele andere.

Eventuell ist da ja etwas dabei.

ub60


Delete - Do 05.11.15 20:42

Zitat:
"The database text encoding:
A value of 1 means UTF-8.
A value of 2 means UTF-16le.
A value of 3 means UTF-16be."
https://www.sqlite.org/fileformat2.html


tastenkleber - Do 05.11.15 22:23

So, jetzt habe ich meine function etwas überarbeitet. Damit kann ich jetzt leben:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function osz(s:unicodestring):utf8string;
var i:Integer;
begin
  // für 2teilige Sonderzeichen:
  for i:= 128 to 191 do
    s:= Replacestr(s,#195+Ansichar(i),chr(i+64));

  s:= Replacestr(s,#10#13,''); // Zeilenumbruch auch noch weg

 result :=s;
end;


Die Laz-function UnicodeToUTF8 scheint wohl zu passen (hab ich aber noch nicht ausprobiert). Sowas ähnliches steht auch in den Konvertierungsfunktionen von Embarcadero - doch die war leider nicht zielführend.

Ich danke für Eure hilfreichen Antworten.


rushifell - Fr 06.11.15 09:59

Hast Du schonmal UTF8Decode ausprobiert? Damit sollte es eigentlich funktionieren. Das UTF8Encode in Zeile 3 Deines Quelltextes macht hier keinen Sinn, da es in UTF8 "kodiert". Du willst aber "dekodieren".

Viele Grüße


tastenkleber - Fr 06.11.15 17:00

@rushifell

Nee - geht leider auch nicht. Was dabei herauskommt, s.Bild

listbild

Es sollte aber so aussehen:

listbild2

Das krieg ich mittlerweile mit meiner function hin.
(ist ja jetzt auch nur noch ein 3-Zeiler)

Gruß Jörg

Moderiert von user profile iconNarses: Bilder als Inline-Anhänge hochgeladen.