2010-05-29 13 views
27

Al examinar los atributos de UTF-16 y UTF-8, no puedo encontrar ninguna razón para preferir UTF-16.¿Hay alguna razón para preferir UTF-16 a UTF-8?

Sin embargo, mirando Java y C#, parece que las cadenas y caracteres están predeterminados en UTF-16. Estaba pensando que podría ser por razones históricas, o quizás por motivos de rendimiento, pero no pude encontrar ninguna información.

¿Alguien sabe por qué estos idiomas eligieron UTF-16? ¿Y hay alguna razón válida para que yo haga eso también?

EDITAR: Mientras tanto, también encontré this answer, que parece relevante y tiene algunos enlaces interesantes.

+3

Además de mi respuesta, yo diría que .NET/C# eligió UTF-16 porque esa es la codificación "nativo" de Windows: es más fácil de Interop con Windows nativo si usted está utilizando el misma codificación –

+1

¿Con qué fines elige una codificación? UTF-16 es una opción razonable para el manejo de cadenas en memoria, como lo es 'wchar_t', que será UTF-16 en Windows y generalmente UTF-32 en otros lugares. Pero para los protocolos en línea y el almacenamiento de archivos, UTF-8 es casi siempre la mejor opción. – bobince

+2

@codeka: estoy de acuerdo (le di +1), pero también se podría hacer la pregunta "¿por qué la codificación nativa de Windows UTF-16 y no UTF-8?". –

Respuesta

31

Los idiomas de Asia Oriental generalmente requieren menos almacenamiento en UTF-16 (2 bytes son suficientes para el 99% de los caracteres del idioma de Asia oriental) que UTF-8 (normalmente se requieren 3 bytes).

Por supuesto, para lanagues occidentales, UTF-8 es generalmente más pequeño (1 byte en lugar de 2). Para archivos mixtos como HTML (donde hay un montón de marcas) es mucho de una gran cosa.

El procesamiento de UTF-16 para aplicaciones en modo de usuario es ligeramente más fácil que procesar UTF-8, porque los pares de sustitución se comportan casi de la misma manera que los caracteres de combinación. Por lo tanto, UTF-16 generalmente se puede procesar como una codificación de tamaño fijo.

+1

+1 Para caracterizar correctamente el número de bytes por carácter en UTF-16 y UTF-8. – Joren

+1

Pensé que UTF-8 puede codificar hasta 4 bytes, lo que prácticamente hace que UTF-16 y UTF-32 sean inútiles. –

+1

@Sir Psycho: UTF-8 es una codificación de longitud variable, que es más compleja de procesar que una codificación de longitud fija. Además, vea mis comentarios sobre la respuesta de Gumbo: básicamente, existen caracteres combinados en todas las codificaciones (UTF-8, UTF-16 y UTF-32) y requieren un manejo especial. Puedes usar el mismo manejo especial que usas para combinar personajes para manejar pares sustitutos en UTF-16, entonces * en su mayor parte * puedes ignorar los sustitutos y tratar el UTF-16 como una codificación fija. –

2

Para muchas aplicaciones (¿la mayoría?), Tratará únicamente caracteres en el Basic Multilingual Plane, por lo que puede tratar a UTF-16 como una codificación de longitud fija.

Para evitar toda la complejidad de las codificaciones de longitud variable como UTF-8.

+3

+1, de hecho, creo que la versión 1 de Unicode solo tenía lo básico, razón por la cual una serie de plataformas suponía que 16 bits sería el tamaño correcto para un tipo de datos de carácter simple. –

+1

"Creo que la versión 1 de Unicode solo tenía lo básico" - sí, es cierto, más detalles aquí: http://en.wikipedia.org/wiki/UTF-16/UCS-2 – Joe

+5

Eso es como decir "solo un montón de programas" se preocupan por ASCII, por lo que pueden tratar UTF-8 como una codificación de longitud fija ". – dan04

3

Depende de los juegos de caracteres esperados. Si espera un uso intensivo de los puntos de código Unicode fuera del rango ASCII de 7 bits, es posible que UTF-16 sea más compacto que UTF-8, ya que algunas secuencias UTF-8 tienen más de dos bytes de longitud.

Además, por razones de eficiencia, Java y C# no tienen en cuenta los pares de sustitución al indexar las cadenas. Esto se rompería por completo al usar puntos de código que están representados con secuencias UTF-8 que ocupan un número impar de bytes.

+0

¿Podría explicarnos más acerca de "Java y C# no toman en cuenta los pares suplentes al indexar strings "? – Oak

+1

Si tiene una cadena en C# (o Java) que contiene pares sustitutos (los SP se usan para codificar caracteres fuera del rango normal de dos bytes), cada par contará como dos caracteres de 16 bits, en lugar de 1 Punto de código Unicode. Al menos para fines de indización e informes de longitud. – corvuscorax

6

Imagino que C# usando UTF-16 proviene de la familia de sistemas operativos Windows NT que usan UTF-16 internamente.

Me imagino que hay dos razones principales por las que Windows NT utiliza UTF-16 internamente:

  • Para el uso de memoria: UTF-32 se desperdicia mucho de espacio para codificar.
  • Para rendimiento: UTF-8 es mucho más difícil decodificar que UTF-16 . En UTF-16, los caracteres son , un personaje Básico de Plano Multilingüe (2 bytes) o un Sustituto Par (4 bytes). Los caracteres UTF-8 pueden estar en cualquier lugar entre 1 y 4 bytes.

Contrariamente a lo que otras personas han respondido, no puede tratar a UTF-16 como UCS-2. Si desea iterar correctamente sobre los caracteres reales en una cadena, debe usar funciones de iteración que sean amigables con unicode. Por ejemplo, en C# necesita usar StringInfo.GetTextElementEnumerator().

Para más información, esta página en el wiki de la pena leer: http://en.wikipedia.org/wiki/Comparison_of_Unicode_encodings

+0

¡Ah, y no olvide combinar caracteres! (Lo que 'GetTextElementEnumerator' también manejará). –

+2

"... no se puede tratar UTF-16 como UCS-2", pero sí muchas aplicaciones exitosas del mundo real, y salirse con la suya porque solo están usando caracteres BMP. – Joe

+0

Enlace muy útil, gracias! – Oak

3

UTF-16 puede ser más eficiente para la representación de caracteres en algunos idiomas como el chino, japonés y coreano, donde más caracteres pueden ser representados en una palabra de 16 bits. Algunos caracteres raramente utilizados pueden requerir dos palabras de 16 bits. UTF-8 generalmente es mucho más eficiente para representar caracteres de conjuntos de caracteres europeos occidentales: UTF-8 y ASCII son equivalentes en el rango ASCII (0-127), pero menos eficientes en los idiomas asiáticos, que requieren tres o cuatro bytes para representar caracteres que se puede representar con dos bytes en UTF-16.

UTF-16 tiene una ventaja como formato en memoria para Java/C# ya que cada personaje en el plano multilingüe básico puede representarse en 16 bits (vea la respuesta de Joe) y algunas de las desventajas de UTF-16 (por ejemplo, código confuso que depende de \ 0 terminadores) son menos relevantes.

10

@Oak: esta demasiado largo para un comentario ...

No sé sobre C# (y estaría muy sorprendido: que significaría que sólo copian Java demasiado mucho), pero para Java es simple: Java fue concebido antes de que saliera Unicode 3.1.

Por lo tanto, había menos de 65537 puntos de código, por lo tanto, todos los puntos de código Unicode todavía se ajustaban a 16 bits, por lo que nació el de Java.

Por supuesto, esto dio lugar a cuestiones locas que siguen afectando a los programadores de Java (como yo) de hoy, donde se tiene un método charAt la que en algún caso no volver ni un carácter Unicode, ni un punto de código Unicode y un método (añadido en Java 5) codePointAt que toma un argumento que no es el número de puntos de código que desea omitir! (debe suministrar codePointAt la cantidad de Java char que desea omitir, lo que lo convierte en uno de los métodos menos entendidos en la clase String).

Así que, sí, esto es definitivamente salvaje y confunde a la mayoría de los programadores de Java (la mayoría ni siquiera son conscientes de estos problemas) y, sí, es por razones históricas. Al menos, esa fue la excusa que surgió cuando la gente se enojó después de este problema: , pero es porque Unicode 3.1 aún no había salido.

:)

Cuestiones relacionadas