![]() |
Re: Unicode-Umwandlung
Bei der String->WideString Zuweisung bastelt Delphi automatisch den MultiByteToWideChar Aufruf in den Code, das klappt aber nicht, wenn z.B. über s:=#$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$00 ein String direkt mit den Bytewerten eines WideString gefüttert wird, die in einem AnsiString normalerweise nicht vorkommen können. Die Bytefolgen oben dürften bereits UTF-16 sein, Shift-JIS sieht anders aus.
Wenn es hier ein Problem gibt, dann vermutlich lediglich das Ausleseergebnis der Datei direkt in einen WideString zu bekommen und nicht irgendwelche Konvertierungen. |
Re: Unicode-Umwandlung
Hallo,
die Zeichenfolge #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$00 ist in Delphi immer ein AnsiString und könnte tatsächlich UTF-16 Hiragana sein. Ich hatte mir den String nicht genau angesehen, weil Windows in Japan mit CP 932 (Shift-JIS) arbeiten soll. Das Arbeiten mit dem Literal ist ja wohl nur ein Test, da ja der eigentliche Dateiname über eine Funktion ermittelt wird. Die Interpretation als WideString ist so möglich:
Delphi-Quellcode:
Freundliche Grüße
var
s: string; ws: WideString absolute s; begin s := #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$00; ShowMessage(ws); end; |
Re: Unicode-Umwandlung
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
benennt meine Datei testa in S0Œ0o0^—8 um...
begin
MoveFileW('testa', #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$00); end; Und folgender Code:
Delphi-Quellcode:
macht gar nichts. Ich habe am Ende noch eine Nullterminierung (bei Unicode $00 $00) hinzugefügt. Aber irgendwie funktioniert das nicht. Die Datei sollte sich in これは非常に短いテキストである.idx umbennen.
begin
MoveFileW('testa', #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$5E#$6B#$30#$ED#$77#$44#$30#$C6#$30#$AD#$30#$B9#$30#$C8#$30#$67#$30 + #$42#$30#$8B#$30#$02#$30#$2E#$00#$69#$00#$64#$00#$78#$00#$00); end; Weiß irgendwer Rat? Ich bin im Moment total verwirrt mit Unicode und WideChar, WideString und Pointern usw... Ist eine Grauzone in meinem Gebiet. Gruß blackdrake [edit=mkinzler]Umbruch in Code eingefügt Mfg, mkinzler[/edit] |
Re: Unicode-Umwandlung
Was soll Delphi denn machen? In der Funktion steht eine Folge von Charwerten, für Delphi ist das natürlich ein AnsiString; #$53='S', #$30='0' usw., den es damit hilfsbereit vor dem Funktionsaufruf erst einmal zum WideString macht, in der Annahme jedes Byte bedeutet ein eigenes Zeichen.
Zum Versuchen kannst du die Sache einem AnsiString zuweisen und entweder wie marabu einen WideString mit dem gleichen Speicherbereich benutzen (aber besser mit MessageBoxW und nicht ShowMessage) oder halt die Pseudokonvertierung PWChar(@s[1]) probieren. Ich denke aber, dass das alles gar nicht notwendig ist. Die Schwierigkeiten bei den Beispielen kommen vor allem durch die direkte Bytezuweisung der Hexeditorergebnisse an einen AnsiString (ein WideChar in 2 ausgewiesene Char). Sollte bei deinem Vorhaben aber gar nicht auftreten, wenn du den Namen bereits als WideString=UTF-16 aus der Datei herausliest. Wichtig ist also die Routine, mit der du die Datei ausliest. |
Re: Unicode-Umwandlung
Hallo.
Ich habe es aufgrund der Vorlage von Ydobon herausgefunden, wie es funktioniert! :P
Delphi-Quellcode:
Ich muss jetzt also beim Papierkorb bei der Info2 Auslesung beim richtigen Offset solange 2 Bytes einlesen, bis ein Byte-Paar $00 $00 ist. Dann höre ich auf, die Bytepaare an s (string) anzuhängen. Die $00 $00 Null-Terminierung muss nicht bei movefilew() vorhanden sein.
function unicode(inp: string): PWideChar;
begin result := PWChar(@inp[1]); end; procedure TForm1.Button1Click(Sender: TObject); begin movefilew('testa', unicode(#$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$5E#$6B#$30#$ED#$77#$44#$30#$C6#$30#$AD#$30#$B9#$30#$C8#$30#$67#$30#$42#$30#$8B#$30 + #$02#$30#$2E#$00#$69#$00#$64#$00#$78#$00)); end; Gruß blackdrake [edit=mkinzler]Umbruch in Code eingefügt Mfg, mkinzler[/edit] |
Re: Unicode-Umwandlung
Hi,
Dein Code ist so nicht wirklich sauber. Du gibst hier einen Zeiger auf einen Speicherbereich zurück, von dem Du nicht weißt wie lang dieser gültig ist. Am deutlichsten kann man das an einem Beispiel machen:
Delphi-Quellcode:
Der Zeiger, den Unicode liefert, der zeigt in doFoo, nach dem Aufruf von unicode(s) noch auf das erste Element von s. Wird die Funktion verlassen, wird s durch Delphi frei gegeben, das Ergebnis der Funktion zeigt aber weiterhin auf diesen Speicher. In doBar steht jetzt eine Adresse zur Verfügung, die ins Daten-Nirvana zeigt. Mit etwas Glück bekommst Du nur eine Zugriffsverletzung, da Delphi erkennt, dass Du auf ungültigen Speicher zugreifst. Mit etwas Pech liest/schreibst Du zufällig irgendwo in den Speicher (Deines Programms) und hast ein undefiniertes Verhalten. Dieses Verhalten kann sich bei jedem Aufruf völlig anders verhalten (je nachdem was gerade wo im Speicher steht und was Du zufällig überschreibst), solche Fehler sind deswegen sehr schwer zu finden!
function doFoo: PWideChar;
var s: String; begin s := #$53#$30#$8C#$30$00$00; result := unicode(s); end; procedure doBar; var p: PWideChar; begin p := doFoo; // und hier knallt es dann beim Zugriff auf p end; Besser ist es deshalb, wenn Du in der Methode einen neuen Speicherbereich allozierst und dessen Adresse zurückgibst. Wichtig ist es dann, dass Du auch für die Freigabe sorgen musst (aber bis zur expliziten Freigabe wäre die Adresse gültig!).
Delphi-Quellcode:
Das Ydobon eigentlich meinte (gerade mal gelesen) war sicherlich, dass Du im gleichen Scope wie der String (also ohne Aufruf der Funktion unicode) diesen Cast hättest durchführen können, auch das ist natürlich möglich:
function unicode(inp: string): PWideChar;
begin GetMem(result, length(inp)); Move(inp[1], result, length(inp)); end; procedure TForm1.Button1Click(Sender: TObject); var ustr: PWideChar; begin ustr := unicode(#$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$5E#$6B#$30#$ED#$77#$44#$30#$C6#$30#$AD#$30#$B9#$30#$C8#$30#$67#$30#$42#$30#$8B#$30#$02#$30#$2E#$00#$69#$00#$64#$00#$78#$00); movefilew('testa', ustr); FreeMem(ustr); // erst hier wird ustr ungültig end;
Delphi-Quellcode:
Hier ist die Adresse für den Aufruf von movefilew gültig, da die aufgerufene Methode synchron arbeitet. Kritisch wäre das erst, wenn Du hier eine asynchrone Methode hast, die also parallel abgearbeitet wird und vor der vollständigen Bearbeitung zurückkehrt.
procedure TForm1.Button1Click(Sender: TObject);
var ustr: PWideChar; begin ustr := #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$5E#$6B#$30#$ED#$77#$44#$30#$C6#$30#$AD#$30#$B9#$30#$C8#$30#$67#$30#$42#$30#$8B#$30#$02#$30#$2E#$00#$69#$00#$64#$00#$78#$00; movefilew('testa', PWideChar(@ustr[1])); end; Gruß Der Unwissende |
Re: Unicode-Umwandlung
Mal so nebenbei, könntet ihr eure überlangen Strings bitte auf mehrere Zeilen verteilen, da genügt schon ein '+', mein Bilschirm ist einfach nicht so groß.
Abgesehen von der Sauberkeit der Codes (Wie sicher ist eigentlich der Speicherbereich einer lokalen Variable außerhalb ihrer Funktion?) sollte blackdrake mit Konvertierungen gar nichts zu tun haben, da alles schon als Unicode also WideString vorliegt. Es geht eine Routine zum Auslesen der Datei bereits als WideString. |
Re: Unicode-Umwandlung
Hallo.
Ich habe die Funktion fertiggestellt: ![]() Die Auslagerung in Unicode() habe ich dabei entfernt - war nur hier zur Vereinfachung. Ich gehe mal davon aus, dass der Code in meiner Funktion nun sauber ist, da ich auf einen Speicherbereich zeige, der in der Funktion noch verfügbar ist.
Delphi-Quellcode:
Ist das jetzt also OK?
var
s: string; buf2: array[0..1] of char; ... fs.seek(unicode_source_position+i*record_length, soFromBeginning); s := ''; repeat fs.ReadBuffer(buf2[0], 1); fs.ReadBuffer(buf2[1], 1); if (buf2[0] = #0) and (buf2[1] = #0) then break else s := s + buf2[0] + buf2[1]; until false; result := PWChar(@s[1]); // Unicode-Umwandlung ... Gruß blackdrake |
Re: Unicode-Umwandlung
Hallo,
wieso verwendest Du eigentlich nicht gleich einen WideString? Ungefähr so:
Delphi-Quellcode:
Außerdem gibst Du wohl immer noch einen Pointer auf eine lokale Variable zurück. Das geht nach hinten los. Gib lieber einen WideString zurück und verwende diesen.
function ReadWideString(const Stream: TStream): WideString;
var S: WideString; WC: WideChar; begin S := ''; repeat Stream.ReadBuffer(WC, 2); if (WC <> #0) then S := S + WC; until WC = #0; Result := S; end; Gruß xaromz |
Re: Unicode-Umwandlung
@xaromz: Vielen Dank für die Funktion!
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:20 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