Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   UTF8 Widestring aus 2Byte Hexcode D2007 (https://www.delphipraxis.net/165701-utf8-widestring-aus-2byte-hexcode-d2007.html)

taveuni 12. Jan 2012 08:44

UTF8 Widestring aus 2Byte Hexcode D2007
 
Hallo Leute,

Ich hab nun schon einen Tag gesucht. Auch vieles gefunden. Nur die Lösung nicht.
Wir haben hier ein eigenartiges Projekt auf welches ich auch nicht eingehen möchte.
Tatsache ist:
- Es läuft noch auf D2007
- Es werden keine VCL Komponenten verwendet.

Gegeben sind diverse UTF8 codierte Felder in einer MySql Datenbank.
Nun steht da z.b. drin: d180d183d181d181d0bad0b8d0b920d18fd0b7d18bd0ba
Ich lese dies via Devart Query aus.
Nun kommt das spannende: Ich muss diesen "parsen" und das Ergebnis in ein anderes Feld schreiben:
русский язык (= russische Sprache von hier)

Den umgekehrten Weg habe ich in einem Testprojekt.
Das .pas als UTF8 gespeichert mit einer Konstante:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  s,r: WideString;
begin
  //  s:= 'русский язык';
  s := 'р'; // erstes Zeichen aus obigem String
  r := UTF8ToHexStr(s); // r --> D180
end;

function UTF8ToHexStr(source : WideString) : WideString;
var
  i: Integer;
  ss : TStringStream;
  buffer : Array[0..128] of Byte;
begin
  Result := '';
  ss := TStringStream.Create(UTF8Encode(source));
  Try
    ss.Position := 0;
    ss.Read(buffer, ss.Size);
    for i := 0 to ss.Size - 1 do
      Result := Result + intToHex(buffer[i], 2);
  Finally
    ss.Free;
  End;
end;
An dem Versuch z.b. dieses wieder in einen Widestring bringen bin ich gescheitert.
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
  s: WideString;
begin
  s:= HexStrToUTF8('D180');
end;

function HexStrToUTF8(HexString: String): WideString;
var
  i,x , Size, Pos: Integer;
begin
  Result:= '';
  Pos:= 0;
  Size:= Length(HexString);
  while Pos < Size do
  begin
    x:= StrToInt('$'+copy(HexString,Pos,4)); // zwischenvariable hier habe ich den korrekten Dec Wert 53632 welcher HEX D180 entspricht.

    // für 1 Byte wäre jetzt einfach die Funktion Chr(x) anzuwenden.
    // Result:= Result + Chr(StrToInt('$'+copy(HexString,Pos,4)));


// Was zum Geier muss ich in diesem Fall tun unten einige hilflose Versuche?
//    Result : WideChar(x);
//    x:= MultiByteToWideChar(CP_UTF8,MB_PRECOMPOSED,'',StrToInt('$'+copy(HexString,Pos,4)),nil,0);
//    x:= MultiByteToWideChar(CP_UTF8,MB_PRECOMPOSED,PChar('$'+copy(HexString,Pos,4)),-1,nil,0);
//    Result:= Result + Chr(MultiByteToWideChar(CP_UTF8,MB_PRECOMPOSED,'',StrToInt('$'+copy(HexString,Pos,4)),nil,0));

    Inc(Pos,4);
  end;
end;
Danke für jede Hilfe

himitsu 12. Jan 2012 09:20

AW: UTF8 Widestring aus 2Byte Hexcode D2007
 
Delphi-Quellcode:
UTF8String/AnsiString<<< := HexStrToUTF8('D180')
s := >>>WideString
uvm.

Wenn du ganz sicher gehn willst, dann solltest du dich nicht immer Blindlinks auf die automatische Umcodierung verlassen.

Meckert nicht auch schon der D2007-Compiler über die "unsicheren" Konvertierungen?



[edit]
Zitat:

Delphi-Quellcode:
function HexStrToUTF8(HexString: String): WideString;

:wall:
UTF8 oder unkodiertes Unicode?

taveuni 12. Jan 2012 10:13

AW: UTF8 Widestring aus 2Byte Hexcode D2007
 
Hmhh.. Zugegeben ich habe mich noch nicht wirklich umfassend mit Unicode beschäftigt.

Der Compiler mekert bei der Funktion nicht.
Die ist ja von mir und sehe keinen Grund.
Der String welcher dieser Funktion übergeben wird kann ja ein AnsiString sein.
Dieser wird ja dann Zeichen für Zeichen in der Schleife gelesen und jeweils
4 Zeichen (2Byte) umgewandelt. Erst ab diesen Zeitpunkt möchte ich ja das Ergebnis.


Zitat:

UTF8 oder unkodiertes Unicode?
Wie meinen?

p80286 12. Jan 2012 10:32

AW: UTF8 Widestring aus 2Byte Hexcode D2007
 
UTF8 ist eine 8Bit-Codierung.
Wenn du also UTF8 bkommst, dann ist das gleichbedeutend mit einem Ansi-String in dem einige Zeichen über mehrere Zeichen (Zeichenkombinationen) kodiert wurden.

Das ist so ähnlich wie bei den Druckersteuersprachen. Da wurden Sonderzeichen Fontwechsel etc. auch in den Daten/Buchstabenstrom eingesetzt.

Gruß
K-H

P.S.
UNICODE ist eine 16Bit Codierung, d.h. 2Byte pro Zeichen, immer!

himitsu 12. Jan 2012 10:45

AW: UTF8 Widestring aus 2Byte Hexcode D2007
 
Zitat:

Zitat von p80286 (Beitrag 1145583)
immer!

Bei Google suchenSurrogate Pair :angle2:

Low Surrogate (2 Byte) + High Surrogate (nochmal 2 Byte) = ein Unicodezeichen (4 Byte, eigentlich 2,25 Byte) im Bereich von $00010000 bis $0010FFFF

Gausi 12. Jan 2012 10:56

AW: UTF8 Widestring aus 2Byte Hexcode D2007
 
Zitat:

Zitat von p80286 (Beitrag 1145583)
UNICODE ist eine 16Bit Codierung, d.h. 2Byte pro Zeichen, immer!

Unicode hat mit 16Bit erstmal gar nichts zu tun. Unicode hat einfach nur das Ziel, jedem möglichen Zeichen einen "Code", eine Zahl zuzuordnen. Wie dieser Code dann aufgeschrieben bzw. gespeichert wird (UTF8, UTF16-BE, UTF16-LE, UTF32, ...) ist im Grunde zweitrangig.
Für die allermeisten Zeichen reichen 16 Bits aus, daher wird UTF16 oft mit Unicode synonym verwendet - eben weil man mit dieser Codierung praktisch alles schön mit "2 Bytes pro Zeichen" darstellen kann.

p80286 12. Jan 2012 11:59

AW: UTF8 Widestring aus 2Byte Hexcode D2007
 
Geschenkt...
Mir ging's um die Differenzierung zwischen 8Bit-Codierung und der 16Bit-Codierung.
Und mir war UNICODE nur als 16Bit-Codierung bekannt.

Kennt jemand denn die richtigen Begriffe?

Gruß
K-H

taveuni 12. Jan 2012 12:22

AW: UTF8 Widestring aus 2Byte Hexcode D2007
 
O.K. Ich steig zwar noch nicht wirklich umfassend durch aber:

In meinem Fall scheint es sich um UTF8 zu handeln.
Davon ausgehend - und und ebenfalls meine im ersten Post stehende
erste funktionierende Funktion (UTF8ToHexStr()):
Wie kann ich das ganze wieder rückwärts machen?
Der Ansatz den ich gewählt hatte ist dann natürlich falsch da ich nicht
davon ausgehen kann dass ein Zeichen immer 2 Bytes ist.

Von der anderen Seite welche über die Datenbankverbindung nicht UTF8 lesen
und schreiben kann habe ich die 2 Routinen erhalten (Flash Action Script).

Die erste entspricht meiner Ersten:

Code:
function encode(value:String):String {
 var ba:ByteArray = new ByteArray();
 ba.writeUTFBytes(value);
 var len:uint = ba.length;
 var s:String = "";
 for (var i:uint = 0; i < len; i++) {
  s += ba[i].toString(16);
 }
 return s;
}
Die Zweite welche ich eben irgendwie noch umsetzen sollte:

Code:
function decode(value:String):String {
 var ba:ByteArray = new ByteArray();
 var len:uint = value.length;
 for (var i:uint = 0; i < len; i += 2) {
  var c:String = value.charAt(i) + value.charAt(i + 1);
  ba.writeByte(parseInt(c, 16));
 }
 return ba.toString();
}

Hilft das? (Mir nicht)

himitsu 12. Jan 2012 12:39

AW: UTF8 Widestring aus 2Byte Hexcode D2007
 
String+PChar => Delphi-Referenz durchsuchenHexToBin => UTF8String+PAnsiChar

UTF8String+PAnsiChar => Delphi-Referenz durchsuchenBinToHex => String+PChar


Diesen (anscheinend) hexadezimalen UTF-8-kodierten Text nach String (AnsiString bis D2007 und ab D2009 UnicodeString/WideString) zu konvertieren, dabei kann nichts Richtiges rauskommen.
Wenn das UTF-8 drin ist, dann sollte man daraus auch UTF-8 machen.

shmia 12. Jan 2012 13:42

AW: UTF8 Widestring aus 2Byte Hexcode D2007
 
Also hier sind erst mal 2 Funktionen um aus einem Hexstring einen "normalen" Ansistring zu machen (und umgekehrt):
Delphi-Quellcode:
// Beispiel: StrToHexString('Daten') => '446174656E'
function StrToHexString(const s : AnsiString):AnsiString;
begin
   if s = '' then
      Result := ''
   else
   begin
      SetLength(Result, Length(s)*2);
      BinToHex(PAnsiChar(s), PAnsiChar(Result), Length(s));
   end;
end;

// Beispiel: HexStringToStr('446174656E') => 'Daten'
function HexStringToStr(s : AnsiString):AnsiString;
begin
   if Odd(length(s)) then
      Insert('0', s, 1);
   SetLength(Result, Length(s) div 2);
   HexToBin(PAnsichar(s), PAnsiChar(Result), Length(Result));
end;
Nachdem man die Funktion HexStringToStr() aufgerufen hat, muss man nur noch den in UTF8 kodierten String in einen Widestring überführen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:41 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz