2010-09-07 11 views
5

Quiero codificar cadenas como lo hace Python.Delphi: Cadenas de codificación como Python do

código Python es la siguiente:

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

Esto es muy simple.

Pero en Delphi no entiendo, cómo codificar, para forzar primero el conjunto de caracteres buenos (no importa, qué computadora tenemos).

yo probamos este código de prueba para ver la conversión:

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; 

La entrada es: "árvíztűrő tükörfúrógép", la frase húngaro probador de acento. El lc local es 1038 (hun), el nuevo lc es 1033.

Pero esto cada vez hace 0 resultado (mismas cadenas), y los acentos son los mismos, no pierdo ŐŰ que no está en inglés lang.

¿Qué hago mal? ¿Cómo hago lo mismo que Python?

Gracias por toda la ayuda, enlace, etc: dd

Respuesta

7

Windows usa la página de códigos 28592 para ISO-8859-2.Si tiene un búfer que contiene bytes codificados ISO-8859-2, primero tiene que decodificar los bytes a UTF-16 primero, y luego codificar el resultado a UTF-8. Dependiendo de la versión de Delphi que está utilizando, puede:

1) en la pre-D2009, utilice MultiByteToWideChar() y 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) en D2009 +, utilice 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) en D2009 +, definir, alternativamente, una nueva cadena de typedef, poner los datos en él, y asignarla a una variable UTF8String. decodificación necesita ninguna codificación manual de /, la RTL se encargará de todo para usted:

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 no compila para Delphi2009, cambiará mi voto cuando se solucione. – Wodzu

+0

He modificado los ejemplos. –

+0

Gracias Remy, +1 – Wodzu

0

Si está utilizando Delphi 2009 o más reciente cada entrada del defecto controles VCL serán UTF-16, por lo que no hay necesidad de hacer las conversiones en su entrada.

Si está utilizando Delphi 2007 o anterior (como parece) está a merced de Windows, porque la VCL es ANSI y Windows tiene una página de códigos fija que determina qué caracteres se pueden usar en, por ejemplo, un TEdit.

Sin embargo, puede cambiar el CP ANSI predeterminado en todo el sistema en el panel de control, pero eso requiere un reinicio cada vez que lo haga.

En Delphi 2007 tiene la posibilidad de utilizar controles TNTUnicode o alguna solución similar para obtener el texto de la interfaz de usuario en su código.

En Delphi 2009 y posteriores también hay muchas rutinas de manejo de conjuntos de caracteres y Unicode en el RTL.

La conversión entre conjuntos de caracteres se puede hacer con SysUtils.TEncoding:

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

+0

No es necesario reiniciar, felizmente el cambio entre los teclados de Alemania y de Europa del Este y páginas de códigos aquí (incluso en Windows 2000). – mjn

0

hay herramientas de codificación en Open XML biblioteca. Hay una unidad cUnicodeCodecsWin32 con funciones como: EncodingToUTF16().

Mi código que convierte entre ISO latino 2 y UTF-8 se parece a:

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

Tenga en cuenta que las versiones más recientes de Delphi incluyen OpenXML como una biblioteca XML opcional. – mjn

+0

Lo probé con Turbo Delphi (D2006) –

0

código Python en su pregunta devuelve una cadena de codificación UTF-8. Para hacer esto con las versiones de Delphi pre-2009 que puede utilizar un código similar a:

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; 

Tenga en cuenta que esto no cambia la configuración regional del subproceso actual, simplemente pasa los parámetros de la página de código correctas a la API.

+3

O simplemente 'UTF8Encode (WideString (Edit1.Text))' para las versiones de Delphi que tienen UTF8Encode. –

+0

Claro. Sin embargo, esta respuesta estaba destinada a estar cerca del código en la pregunta, con la esperanza de ilustrar dónde está el problema. – mghie

+0

Este ejemplo simple (casting a WideString) no es bueno, porque usamos datos iso-8859-2, pero la máquina donde usamos es inglés, así que perdimos acentos ... :-( – durumdara

Cuestiones relacionadas