2011-03-08 18 views

Respuesta

11

Una función como ésta hará lo que usted necesita:

function UTF8Bytes(const s: UTF8String): TBytes; 
begin 
    Assert(StringElementSize(s)=1); 
    SetLength(Result, Length(s)); 
    if Length(Result)>0 then 
    Move(s[1], Result[0], Length(s)); 
end; 

se le puede llamar con cualquier tipo de cuerda y la RTL se convertirá de la codificación de la cadena que se pasa a UTF-8. Así que no se deje engañar por pensar que debe convertir a UTF-8 antes de llamar, simplemente pase cualquier cadena y deje que el RTL haga el trabajo.

Después de eso, es una copia de matriz bastante estándar. Tenga en cuenta la afirmación que llama explícitamente la suposición sobre el tamaño del elemento de cadena para una cadena codificada en UTF-8.

Si desea obtener el terminador cero se escribirían así:

function UTF8Bytes(const s: UTF8String): TBytes; 
begin 
    Assert(StringElementSize(s)=1); 
    SetLength(Result, Length(s)+1); 
    if Length(Result)>0 then 
    Move(s[1], Result[0], Length(s)); 
    Result[high(Result)] := 0; 
end; 
+0

+1. Will 'Assert (StringElementSize (s) = 1);' alguna vez fallará? –

+1

@Cosmin No, no lo hará. ¡Esa es la cuestión de las aserciones! –

+0

una pregunta ... ¿qué unidad debo agregar para usar StringElementSize()? (Lazarus). Perdón por tales preguntas, soy un novato – Mariusz

4
var S: UTF8String; 
    B: TBytes; 

begin 
    S := 'Șase sași în șase saci'; 
    SetLength(B, Length(S)); // Length(s) = 26 for this 22 char string. 
    CopyMemory(@B[0], @S[1], Length(S)); 
end. 

Según lo que necesite para los bytes, es posible que desee incluir un terminador NULL.

Para el código de producción, asegúrese de probar la cadena vacía. Agregar el 3-4 LOC requerido simplemente dificultaría la lectura de la muestra.

+0

Se produce un error si la cadena está vacía –

+1

La cadena no está vacía. Contiene el valor '' Şase saşi în şase saci'' –

+0

+1. ¡No todos (por decir lo menos!) Saben cómo funciona realmente la función 'Longitud '. –

8

Usted puede utilizar TEncoding.UTF8.GetBytes en SysUtils.pas

+0

+1. Esta es la mejor manera. –

+5

Tenga en cuenta que si la cadena de entrada * ya * está codificada como UTF-8, 'GetBytes' será un desperdicio. El compilador convertirá la cadena de entrada en UnicodeString ya que es el único argumento de cadena que permite 'GetBytes', y' GetBytes' convertirá los caracteres a UTF-8 para generar su resultado. –

5

Si está utilizando Delphi 2009 o posterior (el Unicode versiones), la conversión de un WideString a un UTF8String es una instrucción de asignación simple:

var 
    ws: WideString; 
    u8s: UTF8String; 

u8s := ws; 

el compilador llamará a la función de la biblioteca hay que hacer la conversión, ya que sabe º en los valores de tipo UTF8String tienen una "página de códigos" de CP_UTF8.

En Delphi 7 y posterior, puede utilizar la función de biblioteca proporcionada Utf8Encode. Incluso para versiones anteriores, puede obtener esa función de otras bibliotecas, como el JCL.

También puede escribir su propia función de conversión de uso de la API de Windows:

function CustomUtf8Encode(const ws: WideString): UTF8String; 
var 
    n: Integer; 
begin 
    n := WideCharToMultiByte(cp_UTF8, 0, PWideChar(ws), Length(ws), nil, 0, nil, nil); 
    Win32Check(n <> 0); 
    SetLength(Result, n); 
    n := WideCharToMultiByte(cp_UTF8, 0, PWideChar(ws), Length(ws), PAnsiChar(Result), n, nil, nil); 
    Win32Check(n = Length(Result)); 
end; 

Una gran parte del tiempo, sólo tiene que utilizar un UTF8String como una matriz, pero si realmente necesita una matriz de bytes, se puede usar las funciones de David y Cosmin. Si está escribiendo su propia función de conversión de caracteres, puede omitir el UTF8String e ir directamente a una matriz de bytes; simplemente cambie el tipo de devolución a TBytes o array of Byte. (También es posible que desee aumentar la longitud en uno, si desea que la matriz sea terminada en nulo. SetLength lo hará implícitamente a la cadena, pero a una matriz.)

Si tiene algún otro tipo de cadena que sea ni WideString, UnicodeString ni UTF8String, entonces la forma de convertirlo a UTF-8 es primero convertirlo a WideString o UnicodeString, y luego convertirlo nuevamente a UTF-8.

1

He los siguientes dos rutinas (código fuente puede ser descargado aquí - http://www.csinnovations.com/framework_utilities.htm):

función CsiBytesToStr (const pInData: TByteDynArray; pStringEncoding: TECsiStringEncoding; pIncludesBom: Boolean): string;

función CsiStrToBytes (const pInStr: cadena; pStringEncoding: TECsiStringEncoding; pIncludeBom: Boolean): TByteDynArray;