9

Delphi 2007 では、UTF-8 文字列を WideString に格納し、それを Win32 関数に渡すことができます。

var
  UnicodeStr: WideString;
  UTF8Str: WideString;
begin
  UnicodeStr:='some unicode text';
  UTF8Str:=UTF8Encode(UnicodeStr);
  Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;

Delphi 2007 は、UTF8Str の内容に干渉しません。つまり、WideString に格納された UTF-8 でエンコードされた文字列として残されます。

しかし、Delphi 2010 では、同じことを行う方法を見つけるのに苦労しています。つまり、UTF-8 から自動的に変換されずに、UTF-8 でエンコードされた文字列を WideString に格納します。UTF-8 文字列 (または RawByteString) へのポインターを渡すことができません。たとえば、次のようなものは明らかに機能しません。

var
  UnicodeStr: WideString;
  UTF8Str: UTF8String;
begin
  UnicodeStr:='some unicode text';
  UTF8Str:=UTF8Encode(UnicodeStr);
  Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;
4

3 に答える 3

13

元の Delphi 2007 コードは、ANSI コードページを使用して UTF-8 文字列をワイド文字列に変換していました。Delphi 2010 で同じことを行うには、Convert パラメータを false にして SetCodePage を使用する必要があります。

var
  UnicodeStr: UnicodeString;
  UTF8Str: RawByteString;
begin
  UTF8Str := UTF8Encode('some unicode text');
  SetCodePage(UTF8Str, 0, False);
  UnicodeStr := UTF8Str;
  Windows.SomeFunction(PWideChar(UnicodeStr), ...)
于 2010-04-23T13:13:54.130 に答える
3

うーん、なぜそんなことをしているのですか?WideString に再度格納するためだけに、WideString を UTF-8 にエンコードするのはなぜですか。明らかに、Windows API の Unicode バージョンを使用しています。したがって、UTF-8 でエンコードされた文字列を使用する必要はありません。それとも私は何かを逃していますか。

Windows API 関数は Unicode (2 バイト) または ANSI (1 バイト) であるためです。UTF-8 は、主に 1 文字あたり 1 バイトを含むため、ここでは間違った選択になりますが、ASCII ベースより上の文字では 2 バイト以上を使用します。

それ以外の場合、Unicode Delphi の古いコードに相当するものは次のようになります。

var
  UnicodeStr: string;
  UTF8Str: string;
begin
  UnicodeStr:='some unicode text';
  UTF8Str:=UTF8Encode(UnicodeStr);
  Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;

WideString と文字列 (UnicodeString) は似ていますが、新しい UnicodeString は参照カウントされ、WideString はそうでないため、より高速です。

UTF-8 文字列は 1 文字あたりのバイト数が可変であるため、コードは正しくありません。「A」は 1 バイトとして格納されます。ただのASCIIバイトコード。一方、「ü」は 2 バイトとして格納されます。また、PWideChar を使用しているため、関数は常に 1 文字あたり 2 バイトを想定しています。

別の違いがあります。古いバージョンの Delphi (ANSI) では、Utf8String は単なる AnsiString でした。Delphi の Unicode バージョンでは、Utf8String は背後に UTF-8 コード ページを持つ文字列です。そのため、動作が異なります。

古いコードはまだ正しく動作します:

var
  UnicodeStr: WideString;
  UTF8Str: WideString;
begin
  UnicodeStr:='some unicode text';
  UTF8Str:=UTF8Encode(UnicodeStr);
  Windows.SomeFunction(PWideChar(UTF8Str), ...)
end;

Delphi 2007 と同じように動作します。そのため、別の場所で問題が発生している可能性があります。

ミックあなたは正しいです。コンパイラは、バックグラウンドで追加の作業を行います。したがって、これを回避するには、次のようにします。

var
  UTF8Str: AnsiString;
  UnicodeStr: WideString;
  TempString: RawByteString;
  ResultString: WideString;
begin
  UnicodeStr := 'some unicode text';
  TempString := UTF8Encode(UnicodeStr);
  SetLength(UTF8Str, Length(TempString));
  Move(TempString[1], UTF8Str[1], Length(UTF8Str));
  ResultString := UTF8Str;
end;

確認しましたが、同じように動作します。メモリ内でバイトを直接移動するため、バックグラウンドでコードページ変換が行われません。もっと優雅にできると確信していますが、要点は、これがあなたが達成したいことへの道であると私が見ているということです.

于 2010-04-23T11:17:45.667 に答える
0

UTF-8 文字列を渡す必要がある Windows API 呼び出しはどれですか? ANSI 文字列または Widestring (A または W 関数) のいずれかです。ワイド文字列は 1 文字あたり 2 バイトであり、UTF-8 文字列は 1 文字 (最初の 128 ASCII 文字を超えている場合はそれ以上) です。

Widestring の UTF-8 は意味がありません。UTF-8 文字列へのポインターを必要とする Windows 関数が実際にある場合は、おそらく PAnsiChar にキャストする必要があります。

于 2010-04-23T11:12:19.800 に答える