![]() |
Unicode Frage
Hallo,
aus einem String "0" wird ja wenn ich denn nach Unicode umwandele -> $#00 + "0" + $#00 Ich habe das jetzt immer in einer Schleife gemacht (Verzeichnisname -> Unicode)
Delphi-Quellcode:
Jetzt habe ich aber bei einem User (Russischer Zeichensatz) ein Problem, dass er das Verzeichnis nicht findet. Mit großer Wahrscheinlichkeit ist mir hier die oben genannte Routine zum Verhängnis geworden.
result := '';
if s <> '' then begin se := s; while length(se) > 0 do begin result := result + #$00 + se[1]; se := copy(se, 2, length(se)); end; result := result + #$00; end; Bei meinen folgenden Test bin ich auf das Problem gestoßen, dass ich ein Unicodezeichen nicht in ein Char umwandeln kann. "0" ist ja $#00 + "0" - ein Unicodezeichen entspricht also zwei Chars. Mit der unten gezeigten Routine komm ich aber nur an ein Char. Im Beispiel "0" bekomme ich also nur das Zeichen "0" zurück anstatt $#00 + "0".
Delphi-Quellcode:
Ich hoffe ihr versteht mein Problem und habt evt. eine Lösung für mich.
var Test,Test1:PWideChar;
i : integer; sm : string; begin Test := AllocMem(length(s)*2); try Test1:=StringToWideChar(s,Test,length(s)*2); result := ''; sm := ''; for i := 0 to Length(Test1) do begin //Result := Result + sm := sm + ' ' + inttostr(ord(test1[i])); end; WriteToLog('Test=' + sm); finally // Test1 wird hierdurch auch ungültig FreeMem(Test,length(s)*2); end; Danke schonmal |
Re: Unicode Frage
Hallo Thomas,
das was Du machst ist völlig falsch. Die einzelnen Zeichen (z.B. € = $80) können in der Unicodedarstellung komplett ander Codierung haben (€ = $20AC). Delphi erledigt das - wenn es um Zeichen der aktuellen Codepage geht - völlig automatisch:
Delphi-Quellcode:
Willst Du nun einen Verzeichnisnamen in der Unicode-Darstellung haben, so mußt Du die entsprechenden Win32-API-Befehle in der Unicode-Repräsentation aufrufen (Im TNT-Projekt sind liegen z.B. TOpenDialog in einer Unicode-Version vor).
var
str: String; wStr: WideString; begin str := 'Hallo öäü €'; wStr := str end; Hat nun ein russischer User auf einem russischen (kyrilischen) Windows dein Delphi-Programm, so ist dein Programm ohne weiteres fähig mit Verzeichnissen umzugehen, welche kyrilische Zeichen enthält (jedenfalls die 128 gebräuchlichsten), da an stelle unserer Sonderzeichen (€ - ÿ) die russischen Zeichen in den 8-Bit-Charatersatz eingeblendet sind. Dafür kann er nichts mit unseren Umlauten üöä anfangen. Schau dir mal das ![]() ![]() ![]() |
Re: Unicode Frage
So einfach ist es in meinem Fall nicht. Mit meinem Programm kommuniziere ich mit einem Handy mit Hilfe des Obexprotokols. Die ganze Kommunikation läuft über einen Comport.
Die Verzeichnisse werden auch korrekt dargestellt - sprich das Auslesen und Umwandeln, der vom Handy gelieferten Daten, in einen String funktioniert wunderbar mit folgender Funktion:
Delphi-Quellcode:
Umgekehrt hatte ich das immer mit der schon oben geposteten Funktion (einfach vor jedes Zeichen ein $#00 und den String mit $#00 abschließen) veranstaltet und bisher keine Probleme gehabt.
function TObex.AnsiToStr(s : AnsiString) : string;
function ReplaceEntity(s : string; entity : string = ''; replace : string = '') : string; const cHex = '&#'; cSep = ';'; var d : string; begin if (entity <> '')and(replace <> '') then begin while pos(entity, s) > 0 do s := copy(s, 1, pos(entity, s) - 1) + replace + copy(s, pos(entity, s) + length(entity), length(s)); end else begin while pos(cHex, s) > 0 do begin d := copy(s, pos(cHex, s) + length(cHex), length(s)); d := copy(d, 1, pos(cSep, d) - 1); entity := cHex + d + cSep; replace := chr(StrToInt('$' + d)); s := copy(s, 1, pos(entity, s) - 1) + replace + copy(s, pos(entity, s) + length(entity), length(s)); end; end; result := s; end; var Res : array of WideChar; len : integer; begin result := ''; len := MultiByteToWideChar(CP_UTF8, 0, PChar(s), - 1, nil, 0); if len > 0 then begin setlength(Res, len); MultiByteToWideChar(CP_UTF8, 0, PChar(s), -1, @Res[0], len); result := WideString(PWideChar(@Res[0])); end; if result <> '' then begin result := ReplaceEntity(result, '<', '<'); result := ReplaceEntity(result, '>', '>'); result := ReplaceEntity(result, '&', '&'); result := ReplaceEntity(result, '"', '"'); result := ReplaceEntity(result, ''', ''''); result := ReplaceEntity(result); end; end; Um nun ein Verzeichnis zu wechseln wird der Verzeichnisname genommen, durch die Funktion aus dem ersten Post gejagt (und noch einiges mehr wegen dem Obex Protokol) und das ganze dann als String über den Comport an das Handy geschickt. Wenn nun bei dem russischen User (Handy auf russisch) ein Verzeichnis auf dem Handy gewechselt werden soll, liefert mir der Obex Server im Handy den "Nicht gefunden" Fehler zurück. Von daher tippe ich auf eine falsche Umwandlung des Verzeichnisnamen. Laut Protokol arbeitet der Obexserver mit Unicode. Vielleicht hast du noch einen Tipp für mich. |
Re: Unicode Frage
Im obigen Beispielcode sehe ich CP_UTF8. Da ich das Obex Protokol nicht kenne vermute ich mal das die Kommunikation UTF-8-Codiert abläuft (Der Server wird dann wieder die UTF8-Daten nach Unicode umwandeln).
Dann würde ich dir folgende Umwandlung vorschlagen: Wandle deinen String nach Widestring um (Automatisch von Delphi per "Compiler Magic"). Diesen Widestring wandelst Du nach UTF-8 um. Erhalten Strings gehen den Umgekehrten Weg UTF8 -> Widestring -> String Dazu kannst Du die Funktionen in System.pas verwenden:
Delphi-Quellcode:
function UTF8Encode(const WS: WideString): UTF8String;
function UTF8Decode(const S: UTF8String): WideString; |
Re: Unicode Frage
Ich bin nicht sicher, ob ich problem richtig verstanden, aber hier ist ein Hint:
Du soltest CodePage fuer Strings benutzen:
Delphi-Quellcode:
Die russische CodePage ist 1251 ;)
function WideStringToString(const ws: WideString; codePage: Word): AnsiString;
var l: integer; begin if ws = '' then Result := '' else begin l := WideCharToMultiByte(codePage, WC_COMPOSITECHECK or WC_DISCARDNS or WC_SEPCHARS or WC_DEFAULTCHAR, @ws[1], - 1, nil, 0, nil, nil); SetLength(Result, l - 1); if l > 1 then WideCharToMultiByte(codePage, WC_COMPOSITECHECK or WC_DISCARDNS or WC_SEPCHARS or WC_DEFAULTCHAR, @ws[1], - 1, @Result[1], l - 1, nil, nil); end; end; { WideStringToString } function StringToWideString(const s: AnsiString; codePage: Word): WideString; var l: integer; begin if s = '' then Result := '' else begin l := MultiByteToWideChar(codePage, MB_PRECOMPOSED, PChar(@s[1]), - 1, nil, 0); SetLength(Result, l - 1); if l > 1 then MultiByteToWideChar(CodePage, MB_PRECOMPOSED, PChar(@s[1]), - 1, PWideChar(@Result[1]), l - 1); end; end; { StringToWideString } Und fuer die UTF8 Sachen hast du schon antwort bekomen:
Delphi-Quellcode:
function UTF8Encode(const WS: WideString): UTF8String;
function UTF8Decode(const S: UTF8String): WideString; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:37 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