Hallo,
ich habe das Problem, dass ich mit Delphi 2010 und
Indy etwas heruntergeladen habe über idhttp.get. Der Inhalt ist laut Server-Betreiber UTF-8 codiert, also habe ich folgendes verwendet:
Delphi-Quellcode:
ssResult := TStringStream.Create('', TEncoding.UTF8);
idhttp.Get(_URL, ssResult);
Das Download-Ergebnis ist korrekt und komplett Menschenlesbar, d.h. wenn ich das Result in einem Memo anzeigen lasse, werden üöä richtig dargestellt.
Diesen String muss ich nun auch auswerten, da es sich hierbei um ein JSON handelt. Ich verwendet lkJSON mit Delphi 2010.
Zur Fehlersuche habe ich den problematischen String hier in die Konstante gespeichert.
Delphi-Quellcode:
procedure TForm2.Button3Click(Sender: TObject);
var
i: integer;
t: string;
u: UTF8String;
JSON_Document: TlkJSONbase;
JSON_Element: TlkJSONbase;
title: TlkJSONbase;
const
JSONTEXT = '[{"id":270513903,"title":"Blättern"}]';
begin
u := UTF8Encode(JSONTEXT);
JSON_Document := TlkJSON.ParseText(u); // bis hier ist in Variable u "Blättern" noch korrekt in der "Liste der überwachten Ausdrücke" zu sehen
for i := 0 to JSON_Document.Count - 1 do begin
JSON_Element := JSON_Document.Child[i];
if assigned(JSON_Element) then begin
title := JSON_Element.Field['title'];
if assigned(title) then begin
u := title.Value; // u und title.Value halten nun 'Bl�ttern' bzw. 'Bl?ttern' #3F74
t := UTF8Decode(u); // bringt nix
if copy(t, 3, 1) <> 'ä' then begin
// FEHLER
sleep(0); // für BreakPoint
end;
end;
end;
end;
end;
Innerhalb von lkJSON entsteht das Problem an dieser Stelle:
Delphi-Quellcode:
js := TlkJSONstring.Create;
{$ifdef USE_D2009}
js.FValue := UTF8ToString(ws); // auch bei meinem Delphi 2010 wird diese Zeile verwendet
{$else}
js.FValue := UTF8Decode(ws);
{$endif}
Hier wird aus dem lesbaren Text der Datenmüll.
EDIT: Wenn ich nun in dem o.g. Beispiel
t := UTF8Decode(u); // bringt nix
durch
t := UTF8ENCODE(u);
funktioniert es korrekt, also machen beide Funktionen gerade das Gegenteil von dem, was der Name sagt, bzw. ich von Ihnen erwarte?
"u" ist ja UTF8 codiert.
"t" ist nicht UTF8 codiert und bietet auch als Variable nur ein Byte pro Zeichen (?)
Jetzt speichere ich in "t" etwas rein was die Variable speichermäßig gar nicht aufnehmen kann, und kodiere einen UTF8-String erneut zu UTF8 damit es auch wirklich klappt? Ich bin verwirrt.
Ok, jetzt mal ernsthaft:
Wahrscheinlich sind in Delphi 2010 eh alle "string"-Variablen längt Multibyte, können also von Haus aus UTF8 speichern, und der Datentyp "UTF8String" ist veraltet oder wird nur für explizite Sonderfälle benötigt.
JSON hat wohl die Sonderzeichen zwar im MultiByte-Format zurückgegeben, aber die "Markierung" DASS es MultiByte oder was-auch-immer ist hat wohl gefehlt, so dass die UTF8-Bytes #3F74 als 2 Bytes eines Nicht-MultiByte-Strings interpretiert wurden. Warum!?
Durch das erneute Encodieren als UTF8 wurde diese "Markierung" wieder hergestellt und Delphi ist flexibel genug, um die Sonderzeichen auch dann korrekt in einem "normalen" string darzustellen, wenn dieser nicht Explizit von UTF8 nach
ANSI oder
UNICODE zurückgewandelt wurde.
Das eigentliche Problem ist also schon vor dem Absenden dieses Posts gelöst,
aber vielleicht helfen ja meine Gedankengänge jemandem mit dem selben Problem weiter (Speziell:
Indy + JSON + UFT8 --> TStringStream.Create('', TEncoding.UTF8) !!), und vielleicht kann mir jemand noch 1-2 Sätze dazu sagen, weshalb das mit UTF8Decode/UTF8Encode für mich aktuell nicht ganz nachvollziehbar ist...
Danke, lg!
Delphi 10.4 32-Bit auf Windows 10 Pro 64-Bit, ehem. Delphi 2010 32-Bit auf Windows 10 Pro 64-Bit