2011-01-11 59 views
119

¿Diferencia entre UTF-8 y UTF-16? ¿Por qué los necesitamos?Diferencia entre UTF-8 y UTF-16?

MessageDigest md = MessageDigest.getInstance("SHA-256"); 
String text = "This is some text"; 

md.update(text.getBytes("UTF-8")); // Change this to "UTF-16" if needed 
byte[] digest = md.digest(); 
+2

jon skeet tiene un buen artículo sobre la codificación .... http: //csharpindepth.com/Articles/General/Unicode.aspx –

Respuesta

259

Creo que hay un montón de buenos artículos acerca de esto en la Web, pero aquí hay un breve resumen.

Tanto UTF-8 como UTF-16 son codificaciones de longitud variable. Sin embargo, en UTF-8 un personaje puede ocupar un mínimo de 8 bits, mientras que en UTF-16 la longitud del carácter comienza con 16 bits.

principales UTF-8 pros:

  • caracteres básicos ASCII como dígitos, caracteres latinos sin acentos, etc. ocupan un byte, que es idéntica a la representación US-ASCII. De esta forma, todas las cadenas de caracteres US-ASCII se convierten en UTF-8 válidas, lo que proporciona una retrocompatibilidad decente en muchos casos.
  • Sin bytes nulos, que permite utilizar cadenas terminadas en nulo, esto también ofrece una gran compatibilidad con versiones anteriores.
  • UTF-8 es independiente del orden de bytes, por lo que no tiene que preocuparse por el problema de Big Endian/Little Endian.

principales UTF-8 contras:

  • Muchos caracteres comunes tienen diferente longitud, lo que ralentiza la indexación de punto de código y calculando un recuento de punto de código terriblemente.
  • Aunque el orden de bytes no importa, a veces UTF-8 todavía tiene BOM (marca de orden de bytes) que sirve para notificar que el texto está codificado en UTF-8, y también rompe la compatibilidad con el software ASCII incluso si el texto solo contiene caracteres ASCII. El software de Microsoft (como el Bloc de notas) especialmente le gusta agregar listas de materiales a UTF-8.

principales UTF-16 pros:

  • BMP (plano multilingüe básico) caracteres, incluyendo América, cirílico, la mayoría de los chinos (la República Popular China hicieron soporte para algunos puntos de código fuera de BMP obligatorio), la mayoría de los japoneses pueden ser representado con 2 bytes.Esto acelera la indexación y el cálculo del conteo del punto de código en caso de que el texto no contenga , no, que contengan caracteres suplementarios.
  • Incluso si el texto tiene caracteres suplementarios, todavía están representados por pares de valores de 16 bits, lo que significa que la longitud total aún es divisible por dos y permite usar 16-bit char como el componente primitivo de la cadena.

principales UTF-16 contras:

  • Un montón de bytes nulos en las cadenas US-ASCII, lo que significa que no hay cadenas terminadas en cero, y una gran cantidad de memoria desperdiciada.
  • Su uso como de longitud fija de codificación “en su mayoría trabaja” en muchos escenarios comunes (especialmente en US/EU/países con alfabetos cirílico/árabe/israelí países/Irán y muchos otros), a menudo conduce a la rotura de apoyo donde doesn 't. Esto significa que los programadores deben conocer los pares de sustitución y manejarlos adecuadamente en los casos en que sea importante.
  • Es de longitud variable, por lo que contar o puntos de código de indexación es costoso, aunque menos que UTF-8.

En general, UTF-16 es generalmente mejor para la representación en memoria porque BE/LE es irrelevante allí (sólo tiene que utilizar para nativo) y la indexación es más rápido (pero no te olvides de manejar adecuadamente los pares suplentes). UTF-8, por otro lado, es extremadamente bueno para archivos de texto y protocolos de red porque no hay un problema BE/LE y la terminación nula a menudo es útil, así como la compatibilidad ASCII.

+1

Falta solo parte BE/LE en UTF16 :) UTF-8 tiene otro inconveniente, puede generar una salida más larga que UTF16 – bestsss

+4

Sí, me olvidé de BE/LE. Sin embargo, no es un gran problema, especialmente para el uso en memoria. UTF-8 generará una salida más larga solo si se trata de caracteres de tres bytes, pero eso significa principalmente chino y japonés. Por otro lado, si el texto contiene muchos caracteres US-ASCII, puede generar un resultado más corto, por lo tanto, si es un inconveniente o no, depende de una situación particular. –

+0

Ni siquiera pensé en mencionar el profesional inmediato de utf-8, de menor longitud. Acerca de la salida más larga de utf-8 fue 'may' por una razón, pero si el objetivo está muy al este, la codificación predeterminada debe ser utf-16. En cuanto al ejemplo md.update (text.getBytes ("UTF-8")); la codificación no importa ya que el hash es estable en ambos sentidos. – bestsss

18

Son simplemente diferentes esquemas para representar caracteres Unicode.

Ambos son de longitud variable - UTF-16 utiliza 2 bytes para todos los caracteres en el plano multilingüe básico (BMP) que contiene la mayoría de los caracteres de uso común.

UTF-8 usa entre 1 y 3 bytes para caracteres en BMP, hasta 4 para caracteres en el rango Unicode actual de U + 0000 a U + 1FFFFF, y es extensible hasta U + 7FFFFFFF si eso ocurre alguna vez es necesario ... pero, en particular, todos los caracteres ASCII están representados en un solo byte cada uno.

A los efectos de un resumen de mensaje, no importa cuál de estos elija, siempre y cuando todos los que intenten recrear el resumen utilicen la misma opción.

Consulte this page para más información sobre UTF-8 y Unicode.

(Tenga en cuenta que todos los caracteres de Java son UTF-16 puntos de código dentro de la BMP;. Para representar los caracteres anteriores U + FFFF que necesita para utilizar los pares suplentes en Java)

4

Esto no está relacionado con UTF-8/16 (en general, aunque se convierte a UTF16 y la parte BE/LE se puede establecer con una sola línea), a continuación se muestra la forma más rápida de convertir Cadena en byte []. Por ejemplo: bueno exactamente para el caso provisto (código hash). String.getBytes (enc) es relativamente lento.

static byte[] toBytes(String s){ 
     byte[] b=new byte[s.length()*2]; 
     ByteBuffer.wrap(b).asCharBuffer().put(s); 
     return b; 
    } 
0

La manera simple de diferenciar UTF-8 y UTF-16 es identificar las similitudes entre ellos.

Aparte de compartir mismo número Unicode para caracteres dada, cada uno es su propio formato.