![]() |
UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Hi,
ich hab kürzlich die Funktion UTF8ToAnsi gefunden und wenn in dem String nur UTF8-Zeichen oder "standard" vorkommen, funktioniert alles. Kommen allerdings "normale" Sonderzeichen (ISO-Irgendwas-Zeichensatz), also äöüß vor, bricht die Funktion ab und hinterlässt einen leeren String - nicht grade schön. Ich hab deshalb die Funktion etwas umgeschrieben:
Delphi-Quellcode:
Nach verschiedenen AND/OR-Verknüpfungen wird also abgebrochen, diese Abbrüche hab ich einfach blind ersetzt und es funktioniert. Dass die Lösung nicht sehr schön ist, ist mir klar. Mit anderen Umlauten außer öäüß hab ich die Funktion bisher nicht getestet.
// Das Copyright dieser Funktion liegt bei Borland, ich hab lediglich 4 Zeilen an verschiedenen Stellen ergänzt. Die Funktion findet man in der System.pas wenn man eine Delphi-Version mit Sourcecode der VCL hat.
function _Utf8ToUnicode(Dest: PWideChar; MaxDestChars: Cardinal; Source: PChar; SourceBytes: Cardinal): Cardinal; overload; var i, count: Cardinal; c: Byte; wc: Cardinal; begin if Source = nil then begin Result := 0; Exit; end; Result := Cardinal(-1); count := 0; i := 0; if Dest <> nil then begin while (i < SourceBytes) and (count < MaxDestChars) do begin wc := Cardinal(Source[i]); Inc(i); if (wc and $80) <> 0 then begin if i >= SourceBytes then begin dest[count]:=widechar(source[i-1]); // von mir eingefügt, normal stand hier "exit;" Inc(count); continue; end; // incomplete multibyte char wc := wc and $3F; if (wc and $20) <> 0 then begin c := Byte(Source[i]); Inc(i); if (c and $C0) <> $80 then begin dest[count]:=WideChar(source[i-2]); // von mir eingefügt, normal stand hier "exit;" Inc(count); Dec(i); continue; end; // malformed trail byte or out of range char if i >= SourceBytes then begin dest[count]:=WideChar(source[i-2]); // von mir eingefügt, normal stand hier "exit;" Inc(count); continue; end; // incomplete multibyte char wc := (wc shl 6) or (c and $3F); end; c := Byte(Source[i]); Inc(i); if (c and $C0) <> $80 then begin dest[count]:=widechar(source[i-2]); // von mir eingefügt, normal stand hier "exit;" Inc(count); Dec(i); continue; end; // malformed trail byte Dest[count] := WideChar((wc shl 6) or (c and $3F)); end else Dest[count] := WideChar(wc); Inc(count); end; if count >= MaxDestChars then count := MaxDestChars-1; Dest[count] := #0; end else begin while (i < SourceBytes) do begin c := Byte(Source[i]); Inc(i); if (c and $80) <> 0 then begin if i >= SourceBytes then exit; // incomplete multibyte char c := c and $3F; if (c and $20) <> 0 then begin c := Byte(Source[i]); Inc(i); if (c and $C0) <> $80 then exit; // malformed trail byte or out of range char if i >= SourceBytes then exit; // incomplete multibyte char end; c := Byte(Source[i]); Inc(i); if (c and $C0) <> $80 then exit; // malformed trail byte end; Inc(count); end; end; Result := count+1; end; Meine Frage nun: Wozu sind die ganzen AND/OR-Verknüpfungen da, was wird da überprüft? Und: Wie kann man meine Lösung verbessern? Gibt es da schon Funktionen, mit denen man "gemischte" Strings vereinheitlichen kann? BTW: (Zum testen) UTF8-"ö": ö Vielen Dank & cu |
Re: UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Hab ich das jetzt richtig verstanden ???
Du hast einem UTF8-String direkt ein Sonderzeichen (z.B. das ö) untergeschoben und diesen "defekten" UTF8-String dann an UTF8toAnsi übergeben, worauf dieser Funktion dann natürlich abgestürtzt ist?
Delphi-Quellcode:
Var S: String;
D: PWideChar; S := 'ö'; Utf8ToUnicode(D, 1, PChar(S), 1); Na kein Wunder, dass diese Funktion so reageirte ... schau dir lieber mal das Format eines UTF8-Strings an ... ein UTF8String ist kein AnsiString :warn: |
Re: UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Hi,
also ich hab's so gemacht:
Delphi-Quellcode:
Daraufhin hab ich die Funktion wie oben "gepatcht". Das funktioniert dann.
function ConvertString(S:string):string;
begin result:=UTF8ToAnsi(S); end; // ... ConvertedString:=ConvertString('test'); // funktioniert ConvertedString:=ConvertString('ö'); // funktioniert (UTF8) ConvertedString:=ConvertString('test äöü'); // funktioniert NICHT :( Meintest du das so? Oder ist der Aufruf wie ich ihn gemacht hab doch richtig? Danke & cu |
Re: UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Zitat:
Delphi-Quellcode:
function ConvertString(S:string):string;
begin result:=UTF8ToAnsi(S); // Delphi-Orginal-Funktion if result = '' then // String leer, wenn kein UTF8 -> Orginal Zurückliefern result := S; end; |
Re: UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Genau das meinte ich und genau das ist der Fehler.
ÄÖÜ ist Ansi und nicht UTF8 ... also kannst du das nur andersrum machen AnsiToUTF8. |
Re: UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Hi,
OK - wie überprüf ich denn nun, ob irgendwo Ansi im String vorkommt (bewusst auch Zeichen außer äöü) und wie verhalte ich mich in der Situation richtig, in der ich sowohl UTF8 als auch Ansi parsen will? Danke & cu |
Re: UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Du mußt schon selber wissen, oder der String ein Ansi, UTF, oder sonst irgendein Stringformat hat und dementspechend mußt du dann auch die Funktionen auswählen
Bei Delphi ist ist z.B. der UTF8String indern auch nunr als eine Ableitung des AnsiStrings definiert, wodurch daher keine Programmseitige Unterscheidung möglich ist. Ansi/Wide/UTF8/UTF16/UTF32.... das sind alles Stringformatierungsvarianten, dass heißt, das die alle die Zeichen in einem anderem Format speichern. |
Re: UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Hi,
naja prinzipiell hab ich immer das selbe Stringformat. Ich les den Text von einem Indy-Clientsocket, gesendet wird der vom IRC-Server. Was der IRC-Client nun reinschreibt auf der Gegenseite bleibt ihm überlassen - meistens ANSI, im Falle von XChat halt standardmäßig UTF-8. Die Zeichen werden also alle gleich gespeichert würd ich sagen, deshalb möcht ich ja die UTF8-Zeichen da "rauskonvertieren". Danke & cu |
Re: UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Zitat:
D.h. dein Ansatz würde schon scheitern, wenn nicht UTF8 bzw. 1252-1 verwendet wird. Da ich Indy nicht verwende weiß ich nicht wo du dort nachschauen mußt. |
Re: UTF8ToAnsi (gemodded) und ANSI/UTF8 gemischt
Nachtrag:
Im Grundegenommen kannst du deine "umgebaute" Prozedur wegschmeißen ... da sie ja jetzt Fehlerhaft ist. Aber wenn du nicht nachschauen kannst, was genau ankommen, also ob mal Ansi oder UTF ankommt, kannst du ja einen "nicht" so ganz guten Weg versuchen. Wie gesagt, perfekt ist das nicht. Es wird halt versucht den String von UTF8 nach Ansi umzuwandeln und bei einem Fehler, also wenn der String kein UTF8-String ist, dann wird er als AnsiString verwendet.
Delphi-Quellcode:
Also versuche lieber rauszubekommtn was ankommt und dann dementsprechend diese Daten dann zu verwenden.
SIn := ... // die empfangenen Daten
Try // von UTF8 nach ANSI umwandeln SOut := UTF8ToAnsi(SIn); Except // und bei Fehler die Daten so übernehmen SOut := SIn; End; // SOut enthält jetzt (vermutlich) die Daten im ANSI-Format
Delphi-Quellcode:
PS: in delphi wird standardmäßig das ANSI-Format verwendet,
S := {empfangene Daten}
If {Datenformat der empfangenen Daten = UTF8} Then S := UTF8ToAnsi(S); // Hier hätte man dann S im ANSI-Format (wenn nur ANSI und UTF8 möglich ist) weßhalb derzeit der String und der AnsiString genau das Selbe darstellen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:18 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