2010-09-07 19 views
5

Chcę kodować ciągi znaków w języku Python.Delphi: Kodowanie ciągów znaków jako Python do

kod Python jest taka:

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

To jest bardzo proste.

Ale w Delphi nie rozumiem, jak kodować, najpierw wymusić dobry zestaw znaków (bez względu na to, który komputer mamy).

Próbowałem ten kod testowy, aby zobaczyć Konwersja:

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; 

wejście jest: "árvíztűrő tükörfúrógép" węgierski frazy tester akcent. Lokalny lc to 1038 (hun), nowy lc to 1033.

Ale to za każdym razem daje wynik 0 (te same struny), a akcenty są takie same, nie zgubiłem ŐŰ, co nie jest w języku angielskim.

Co robię źle? Jak zrobić to samo, co robi Python?

Dzięki za każdą pomoc, link, etc: dd

Odpowiedz

7

System Windows używa strony kodowej 28592 dla ISO-8859-2.Jeśli masz bufor zawierający zakodowane bajty ISO-8859-2, musisz najpierw rozszyfrować bajty do UTF-16, a następnie zakodować wynik na UTF-8. W zależności od wersji Delphi używasz, możesz:

1) na pre-D2009, użyj MultiByteToWideChar() i 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) na D2009 +, użyj 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) na D2009 + alternatywnie zdefiniować nową typedef ciąg, umieścić swoje dane w nim i przypisać ją do zmiennej UTF8String. Brak obsługi kodowania/dekodowania potrzeba, RTL będzie obsługiwać wszystko dla Ciebie:

type 
    Latin2String = type AnsiString(28592); 

var 
    inputstr: Latin2String; 
    outputstr: UTF8String; 
begin 
    // put the ISO-8859-2 encoded bytes into inputstr, then... 
    outputstr := inputstr; 
end; 
+0

-1 EncodeToUTF nie skompiluje się dla Delphi2009, zmieni mój głos, kiedy zostanie naprawiony – Wodzu

+0

Mam podkręcone przykłady –

+0

Dzięki Remy, +1 – Wodzu

0

Jeśli używasz Delphi 2009 lub nowszy każde wejście z domyślnego kontrole VCL będzie UTF-16, więc nie trzeba robić żadnych konwersji w wkład.

Jeśli używasz Delphi 2007 lub starszy (jak się wydaje) jesteś na łasce systemu Windows, ponieważ VCL jest ANSI i Windows ma stałą stronę kodową, która określa, które znaki mogą być używane w TEdit.

Możesz zmienić domyślny ANSI CP w całym systemie w panelu sterowania, ale wymaga to ponownego uruchomienia komputera za każdym razem.

W Delphi 2007 masz szansę użyć elementów sterujących TNTU lub innego podobnego rozwiązania, aby pobrać tekst z interfejsu do kodu.

W Delphi 2009 i nowszych jest także wiele procedur obsługi Unicode i zestawu znaków w RTL.

Konwersja między zestawami znaków można zrobić z SysUtils.TEncoding:

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

+0

bez bólu, reboot, szczęśliwie przełączanie klawiatur niemieckich i wschodnioeuropejskich i stron kodowych tutaj (nawet w systemie Windows 2000). – mjn

0

Istnieje kodowania narzędzi w Open XML bibliotece. Jest jednostka cUnicodeCodecsWin32 z funkcjami takimi jak: EncodingToUTF16().

mój kod, który konwertuje pomiędzy ISO latin2 i UTF-8 wygląda następująco:

s2 := EncodingToUTF16('ISO-8859-2', s); 
    s2utf8 := UTF16ToEncoding('UTF-8', s2); 
+0

Należy pamiętać, że nowsze wersje Delphi obejmują OpenXML jako opcjonalną bibliotekę XML. – mjn

+0

Próbowałem go z Turbo Delphi (D2006) –

0

kodu Pythona w swoim pytaniu zwraca ciąg znaków w UTF-8. Aby to zrobić, z pre-2009 Delphi wersji można użyć kodu podobnego do:

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; 

Zauważ, że to nie zmienia aktualnego locale wątek, to po prostu przechodzi odpowiednie parametry stronę kodową API.

+3

Lub po prostu 'UTF8Encode (WideString (Edit1.Text))' dla wersji Delphi, które mają kod UTF8Encode. –

+0

Pewnie. Ta odpowiedź miała jednak być bliska kodowi w pytaniu, mając nadzieję, że ilustruje, gdzie znajduje się problem. – mghie

+0

Ten prosty przykład (odlewanie do WideString) nie jest dobry, ponieważ używamy danych iso-8859-2, ale maszyna została użyta, to jest angielski, więc straciliśmy akcenty ... :-( – durumdara

Powiązane problemy