5

Python のように文字列をエンコードしたい。

Python コードは次のとおりです。

def EncodeToUTF(inputstr):
  uns = inputstr.decode('iso-8859-2')
  utfs = uns.encode('utf-8')
  return utfs

これは非常に簡単です。

しかし、Delphi では、どのようにエンコードするか、最初に適切な文字セットを強制する方法がわかりません (使用しているコンピューターに関係なく)。

変換を確認するために、このテスト コードを試しました。

procedure TForm1.Button1Click(Sender: TObject);
var
    w : WideString;
    buf : array[0..2048] of WideChar;
    i : integer;
    lc : Cardinal;
begin
    lc := GetThreadLocale;
    Caption := IntToStr(lc);
    StringToWideChar(Edit1.Text, buf, SizeOF(buf));
    w := buf;
    lc := MakeLCID(
        MakeLangID( LANG_ENGLISH, SUBLANG_ENGLISH_US),
        0);
    Win32Check(SetThreadLocale(lc));
    Edit2.Text := WideCharToString(PWideChar(w));
    Caption := IntToStr(AnsiCompareText(Edit1.Text, Edit2.Text));
end;

入力は次のとおりです。「árvíztűrő tükörfúrógép」、ハンガリーのアクセント テスター フレーズ。ローカル lc は 1038 (hun)、新しい lc は 1033 です。

しかし、これは毎回0の結果(同じ文字列)になり、アクセントは同じです。英語ではないŐŰを失いませんでした。

私は何を間違っていますか?Python と同じことを行うにはどうすればよいですか?

すべてのヘルプ、リンクなどに感謝します: dd

4

4 に答える 4

7

Windows は、ISO-8859-2 にコードページ 28592 を使用します。ISO-8859-2 でエンコードされたバイトを含むバッファーがある場合は、最初にバイトを UTF-16 にデコードし、次に結果を UTF-8 にエンコードする必要があります。使用している Delphi のバージョンに応じて、次のいずれかを実行できます。

1) D2009 より前では、MultiByteToWideChar() と WideCharToMultiByte() を使用します。

function EncodeToUTF(const inputstr: AnsiString): UTF8String;
var
  ret: Integer;
  uns: WideString;
begin
  Result := '';
  if inputstr = '' then Exit;
  ret := MultiByteToWideChar(28592, 0, PAnsiChar(inputstr), Length(inputstr), nil, 0);
  if ret < 1 then Exit;
  SetLength(uns, ret);
  MultiByteToWideChar(28592, 0, PAnsiChar(inputstr), Length(inputstr), PWideChar(uns), Length(uns));
  ret := WideCharToMultiByte(65001, 0, PWideChar(uns), Length(uns), nil, 0, nil, nil);
  if ret < 1 then Exit;
  SetLength(Result, ret);
  WideCharToMultiByte(65001, 0, PWideChar(uns), Length(uns), PAnsiChar(Result), Length(Result), nil, nil);
end;

2a) D2009+ では、SysUtils.TEncoding.Convert() を使用します。

function EncodeToUTF(const inputstr: RawByteString): UTF8String;
var
  enc: TEncoding;
  buf: TBytes;
begin
  Result := '';
  if inputstr = '' then Exit;
  enc := TEncoding.GetEncoding(28592);
  try
    buf := TEncoding.Convert(enc, TEncoding.UTF8, BytesOf(inputstr));
    if Length(buf) > 0 then
      SetString(Result, PAnsiChar(@buf[0]), Length(buf));
  finally
    enc.Free;
  end;
end;

2b) D2009+ では、代わりに新しい文字列 typedef を定義し、データをそこに入れ、それを UTF8String 変数に割り当てます。手動のエンコード/デコードは不要です。RTL がすべてを処理します。

type
  Latin2String = type AnsiString(28592);

var
  inputstr: Latin2String;
  outputstr: UTF8String;
begin
  // put the ISO-8859-2 encoded bytes into inputstr, then...
  outputstr := inputstr;
end;
于 2010-09-07T20:01:34.043 に答える
0

Delphi 2009以降を使用している場合、デフォルトのVCLコントロールからのすべての入力はUTF-16になるため、入力に対して変換を行う必要はありません。

Delphi 2007以前を使用している場合(見たところ)、VCLはANSIであり、WindowsにはTEditで使用できる文字を決定する固定コードページがあるため、Windowsに翻弄されます。

コントロールパネルでシステム全体のデフォルトのANSICPを変更できますが、変更するたびに再起動する必要があります。

Delphi 2007では、TNTUnicodeコントロールまたは同様のソリューションを使用して、UIからコードにテキストを取得する機会があります。

Delphi 2009以降では、RTLにUnicodeおよび文字セット処理ルーチンも多数あります。

文字セット間の変換は、SysUtils.TEncodingを使用して実行できます。

http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/SysUtils_TEncoding.html

于 2010-09-07T12:01:43.503 に答える
0

OpenXMLライブラリにはエンコーディングツールがあります。cUnicodeCodecsWin32次のような機能を持つユニットがありますEncodingToUTF16()

ISO Latin2とUTF-8の間で変換する私のコードは次のようになります:

  s2 := EncodingToUTF16('ISO-8859-2', s);
  s2utf8 := UTF16ToEncoding('UTF-8', s2);
于 2010-09-07T12:05:04.400 に答える
0

質問の Python コードは、UTF-8 エンコーディングの文字列を返します。2009 年より前のバージョンの Delphi でこれを行うには、次のようなコードを使用できます。

procedure TForm1.Button1Click(Sender: TObject);
var
  Src, Dest: string;
  Len: integer;
  buf : array[0..2048] of WideChar;
begin
  Src := Edit1.Text;
  Len := MultiByteToWideChar(CP_ACP, 0, PChar(Src), Length(Src), @buf[0], 2048);
  buf[Len] := #0;
  SetLength(Dest, 2048);
  SetLength(Dest, WideCharToMultiByte(CP_UTF8, 0, @buf[0], Len, PChar(Dest),
    2048, nil, nil));
  Edit2.Text := Dest;
end;

これは現在のスレッド ロケールを変更しないことに注意してください。正しいコード ページ パラメーターを API に渡すだけです。

于 2010-09-07T12:24:16.313 に答える