¿Por qué necesitamos Unicode?
En los primeros días (no demasiado), todo lo que existía era ASCII. Esto estaba bien, ya que todo lo que se necesitaría eran unos pocos caracteres de control, puntuación, números y letras como los de esta oración. Desafortunadamente, el extraño mundo actual de intercomunicación global y redes sociales no estaba previsto, y no es demasiado inusual ver inglés, العربية, 汉语, עִבְרִית, ελληνικά, y ភាសាខ្មែរ en el mismo documento (espero no romper ninguno navegadores)
Pero por el bien de la discusión, digamos que Joe Average es un desarrollador de software. Insiste en que solo necesitará inglés y, como tal, solo quiere usar ASCII. Esto podría estar bien para Joe el usuario , pero no está bien para Joe el desarrollador de software . Aproximadamente la mitad del mundo usa caracteres no latinos y el uso de ASCII es posiblemente desconsiderado con estas personas, y además de eso, está cerrando su software a una economía grande y en crecimiento.
Por lo tanto, se necesita un conjunto de caracteres que incluya todos los idiomas. Así llegó Unicode. Asigna a cada carácter un número único llamado punto de código . Una ventaja de Unicode sobre otros conjuntos posibles es que los primeros 256 puntos de código son idénticos a ISO-8859-1 y, por lo tanto, también a ASCII. Además, la gran mayoría de los caracteres de uso común son representables por solo dos bytes, en una región llamada Plano Bilingüe Multilingüe (BMP) . Ahora se necesita una codificación de caracteres para acceder a este conjunto de caracteres, y como pregunta la pregunta, me concentraré en UTF-8 y UTF-16.
Consideraciones de memoria
Entonces, ¿cuántos bytes dan acceso a qué caracteres en estas codificaciones?
- UTF-8:
- 1 byte: ASCII estándar
- 2 bytes: árabe, hebreo, la mayoría de las escrituras europeas (más notablemente excluyendo georgiano )
- 3 bytes: BMP
- 4 bytes: todos los caracteres Unicode
- UTF-16:
- 2 bytes: BMP
- 4 bytes: todos los caracteres Unicode
Vale la pena mencionar ahora que los caracteres que no están en el BMP incluyen scripts antiguos, símbolos matemáticos, símbolos musicales y caracteres chinos / japoneses / coreanos (CJK) más raros .
Si trabajará principalmente con caracteres ASCII, entonces UTF-8 es ciertamente más eficiente en memoria. Sin embargo, si está trabajando principalmente con scripts no europeos, el uso de UTF-8 podría ser hasta 1.5 veces menos eficiente en memoria que UTF-16. Cuando se trata de grandes cantidades de texto, como páginas web grandes o documentos largos, esto podría afectar el rendimiento.
Conceptos básicos de codificación
Nota: Si sabe cómo se codifican UTF-8 y UTF-16, pase a la siguiente sección para obtener aplicaciones prácticas.
- UTF-8: para los caracteres ASCII estándar (0-127), los códigos UTF-8 son idénticos. Esto hace que UTF-8 sea ideal si se requiere compatibilidad con el texto ASCII existente. Otros caracteres requieren entre 2 y 4 bytes. Esto se hace reservando algunos bits en cada uno de estos bytes para indicar que es parte de un carácter de varios bytes. En particular, el primer bit de cada byte es
1
evitar el choque con los caracteres ASCII.
- UTF-16: para caracteres BMP válidos, la representación UTF-16 es simplemente su punto de código. Sin embargo, para los caracteres que no son BMP, UTF-16 introduce pares sustitutos . En este caso, una combinación de dos porciones de dos bytes se correlaciona con un carácter no BMP. Estas porciones de dos bytes provienen del rango numérico BMP, pero el estándar Unicode garantiza que no son válidas como caracteres BMP. Además, dado que UTF-16 tiene dos bytes como su unidad básica, se ve afectado por la endianidad . Para compensar, se puede colocar una marca de orden de bytes reservada al comienzo de un flujo de datos que indica endianness. Por lo tanto, si está leyendo la entrada UTF-16, y no se especifica endianness, debe verificar esto.
Como se puede ver, UTF-8 y UTF-16 no son en absoluto compatibles entre sí. Entonces, si está haciendo E / S, ¡asegúrese de saber qué codificación está usando! Para obtener más detalles sobre estas codificaciones, consulte las preguntas frecuentes de UTF .
Consideraciones prácticas de programación
Tipos de datos de caracteres y cadenas: ¿cómo se codifican en el lenguaje de programación? Si son bytes sin procesar, en el momento en que intente generar caracteres que no sean ASCII, puede encontrarse con algunos problemas. Además, incluso si el tipo de carácter se basa en un UTF, eso no significa que las cadenas sean UTF adecuadas. Pueden permitir secuencias de bytes que son ilegales. En general, tendrá que usar una biblioteca que admita UTF, como ICU para C, C ++ y Java. En cualquier caso, si desea ingresar / emitir algo que no sea la codificación predeterminada, primero deberá convertirla.
Codificaciones recomendadas / predeterminadas / dominantes: cuando se le da la opción de elegir qué UTF usar, generalmente es mejor seguir los estándares recomendados para el entorno en el que está trabajando. Por ejemplo, UTF-8 es dominante en la web, y desde HTML5, ha sido la codificación recomendada . Por el contrario, los entornos .NET y Java se basan en un tipo de caracteres UTF-16. Confusamente (e incorrectamente), a menudo se hacen referencias a la "codificación Unicode", que generalmente se refiere a la codificación UTF dominante en un entorno dado.
Soporte de biblioteca: las bibliotecas que está utilizando admiten algún tipo de codificación. ¿Cúal? ¿Apoyan los casos de esquina? Dado que la necesidad es la madre de la invención, las bibliotecas UTF-8 generalmente admitirán caracteres de 4 bytes correctamente, ya que los caracteres de 1, 2 e incluso 3 bytes pueden aparecer con frecuencia. Sin embargo, no todas las bibliotecas UTF-16 supuestas admiten pares sustitutos correctamente, ya que ocurren muy raramente.
Contando caracteres: existen caracteres combinados en Unicode. Por ejemplo, el punto de código U + 006E (n) y U + 0303 (una tilde combinada) forma ñ, pero el punto de código U + 00F1 forma ñ. Deben verse idénticos, pero un algoritmo de conteo simple devolverá 2 para el primer ejemplo, 1 para el último. Esto no es necesariamente incorrecto, pero tampoco puede ser el resultado deseado.
Comparando para igualdad: A, А y Α se ven iguales, pero son latinos, cirílicos y griegos respectivamente. También tiene casos como C y Ⅽ, uno es una letra y el otro un número romano. Además, también tenemos los caracteres combinados a tener en cuenta. Para más información ver Caracteres duplicados en Unicode .
Pares sustitutos: estos aparecen con bastante frecuencia en SO, por lo que solo proporcionaré algunos enlaces de ejemplo:
¿Otros?: