Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Unicode-Umwandlung (https://www.delphipraxis.net/97375-unicode-umwandlung.html)

Ydobon 11. Aug 2007 17:08

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.

marabu 11. Aug 2007 19:14

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:
var
  s: string;
  ws: WideString absolute s;
begin
  s := #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$00;
  ShowMessage(ws);
end;
Freundliche Grüße

blackdrake 11. Aug 2007 22:11

Re: Unicode-Umwandlung
 
Zitat:

Zitat von Ydobon
Ich blick hier anscheinend nicht ganz durch, warum UTF-16 nach UTF-16 wandeln? Wenn ich
Delphi-Quellcode:
var s: String;
    ws: PWideChar;
   l: Integer;
begin
  s := #$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;
  ws:=PWChar(@s[1]);
  TntEdit1.Text:=ws;
bekomm ich (ohne führendes Nullbyte) これは非常に短いテキストである。.idx bzw. mit s := #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38; ergibt sich (+#$00) これは非8. Soll das in etwas herauskommen? Wenn du bereits Unicode hast, dann gibt es da doch nichts mehr umzuwandeln. Wie liest du die Info2 denn aus?

Hallo. In meinem Beispiel soll es wirklich これは非常に短いテキストである (Babelfish: This is a very short text) heißen. Noch habe die die Routine für die Auslesung aus der INFO2 noch nicht geschrieben. Mein Beispielnamen habe ich durch den Hexeditor aus der INFO2 manuell ausgelesen.

Zitat:

Zitat von marabu
Hallo Robert,

Zitat:

Zitat von blackdrake
... Als erstes brauche ich eine Funktion, die ANSI in Unicode umwandelt. ...

wenn Daniel die Funktion StringToWideString() so verwendet, wie er es zeigt - d.h. mit CP_ACP = 0 - dann kann er auch gleich mit einer Zuweisung arbeiten - Delphi macht dann genau das gleiche. Mich macht aber seine Erwähnung von japanischen Zeichen im Kommentar stutzig. Wenn wirklich ein SJIS-Dateiname vorliegt, dann sind die beiden Funktionen hilfreich, da die CodePage unabhängig von der aktuellen frei gewählt werden kann.

Freundliche Grüße

Ich verstehe das ganze nicht so richtig... ich muss doch erstmal Unicode -> WideChar/WideString (?) umwandeln, damit die Datei korrekt umbenannt wird...

Zitat:

Zitat von marabu
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:
var
  s: string;
  ws: WideString absolute s;
begin
  s := #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$00;
  ShowMessage(ws);
end;
Freundliche Grüße

Folgender Code:

Delphi-Quellcode:
begin
  MoveFileW('testa', #$53#$30#$8C#$30#$6F#$30#$5E#$97#$38#$00);
end;
benennt meine Datei testa in S0Œ0o0^—8 um...

Und folgender Code:

Delphi-Quellcode:
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;
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.

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]

Ydobon 11. Aug 2007 23:28

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.

blackdrake 11. Aug 2007 23:33

Re: Unicode-Umwandlung
 
Hallo.

Ich habe es aufgrund der Vorlage von Ydobon herausgefunden, wie es funktioniert! :P

Delphi-Quellcode:
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;
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.

Gruß
blackdrake

[edit=mkinzler]Umbruch in Code eingefügt Mfg, mkinzler[/edit]

Der_Unwissende 12. Aug 2007 10:22

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:
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;
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!

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:
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;
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:

Delphi-Quellcode:
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;
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.

Gruß Der Unwissende

Ydobon 12. Aug 2007 12:19

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.

blackdrake 12. Aug 2007 15:38

Re: Unicode-Umwandlung
 
Hallo.

Ich habe die Funktion fertiggestellt: http://www.delphipraxis.net/internal...t.php?t=116139

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:
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
...
Ist das jetzt also OK?

Gruß
blackdrake

xaromz 12. Aug 2007 17:11

Re: Unicode-Umwandlung
 
Hallo,

wieso verwendest Du eigentlich nicht gleich einen WideString?
Ungefähr so:
Delphi-Quellcode:
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;
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.

Gruß
xaromz

blackdrake 12. Aug 2007 17:23

Re: Unicode-Umwandlung
 
@xaromz: Vielen Dank für die Funktion!


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:39 Uhr.
Seite 2 von 2     12   

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