utf8 especiales caracteres bom php c unicode normalization unicode-normalization

especiales - utf-8 sin bom php



¿De qué se trata el UTF-8 normalizado? (7)

El proyecto ICU (que ahora también tiene una biblioteca PHP ) contiene las clases necesarias para ayudar a normalizar las cadenas UTF-8 para facilitar la comparación de valores al realizar búsquedas.

Sin embargo, estoy tratando de descubrir qué significa esto para las aplicaciones. Por ejemplo, ¿en qué casos quiero "Equivalencia canónica" en lugar de "Equivalencia de compatibilidad", o viceversa?


Todo lo que nunca quiso saber sobre la normalización Unicode

Normalización Canónica

Unicode incluye varias formas de codificar algunos caracteres, especialmente los caracteres acentuados. La normalización canónica cambia los puntos de código en una forma de codificación canónica. Los puntos de código resultantes deberían parecer idénticos a los originales, salvo errores en las fuentes o en el motor de representación.

Cuándo usar

Como los resultados son idénticos, siempre es seguro aplicar la normalización canónica a una cadena antes de almacenarla o mostrarla, siempre que pueda tolerar que el resultado no sea idéntico bit a bit a la entrada.

La normalización canónica viene en 2 formas: NFD y NFC. Los dos son equivalentes en el sentido de que uno puede convertir entre estas dos formas sin pérdida. Comparar dos cadenas bajo NFC siempre dará el mismo resultado que compararlas bajo NFD.

NFD

NFD tiene los personajes completamente expandidos. Esta es la forma de normalización más rápida para calcular, pero los resultados en más puntos de código (es decir, utiliza más espacio).

Si solo desea comparar dos cadenas que no están ya normalizadas, esta es la forma de normalización preferida a menos que sepa que necesita normalización de compatibilidad.

NFC

NFC recombina puntos de código cuando es posible después de ejecutar el algoritmo NFD. Esto lleva un poco más de tiempo, pero da como resultado cadenas más cortas.

Normalización de compatibilidad

Unicode también incluye muchos caracteres que realmente no pertenecen, pero que se usaron en conjuntos de caracteres heredados. Unicode los agregó para permitir que el texto en esos conjuntos de caracteres se procese como Unicode, y luego se vuelva a convertir sin pérdida.

La normalización de compatibilidad los convierte a la secuencia correspondiente de caracteres "reales" y también realiza la normalización canónica. Los resultados de la normalización de compatibilidad pueden no parecer idénticos a los originales.

Los caracteres que incluyen información de formato se reemplazan por otros que no. Por ejemplo, el personaje se convierte en 9 . Otros no implican diferencias de formato. Por ejemplo, el carácter de número romano se convierte en las letras regulares IX .

Obviamente, una vez que se ha llevado a cabo esta transformación, ya no es posible volver a convertir sin pérdidas al juego de caracteres original.

Cuándo usar

El Consorcio Unicode sugiere pensar en la normalización de compatibilidad como una transformación ToUpperCase . Es algo que puede ser útil en algunas circunstancias, pero no debe aplicarse de cualquier manera.

Un caso de uso excelente sería un motor de búsqueda, ya que probablemente desee buscar 9 para que coincida con .

Una cosa que probablemente no debería hacer es mostrar el resultado de aplicar la normalización de compatibilidad al usuario.

NFKC / NFKD

La forma de normalización de compatibilidad viene en dos formas, NFKD y NFKC. Tienen la misma relación que entre NFD y C.

Cualquier cadena en NFKC es inherentemente también en NFC, y lo mismo para NFKD y NFD. Por NFKD(x)=NFD(NFKC(x)) tanto, NFKD(x)=NFD(NFKC(x)) y NFKC(x)=NFC(NFKD(x)) , etc.

Conclusión

En caso de duda, vaya con la normalización canónica. Elija NFC o NFD en función de la relación de espacio / velocidad aplicable o en función de lo que requiera algo con lo que esté interoperando.


Algunos caracteres, por ejemplo, una letra con un acento (por ejemplo, é ) se pueden representar de dos maneras: un único punto de código U+00E9 o la letra normal seguida de una marca de acento combinada U+0065 U+0301 . La normalización ordinaria elegirá uno de estos para representarlo siempre (el único punto de código para NFC, la forma de combinación para NFD).

Para caracteres que podrían representarse mediante múltiples secuencias de caracteres base y marcas combinadas (por ejemplo, "s, punto abajo, punto arriba" versus poner punto arriba y luego punto abajo o usar un carácter base que ya tiene uno de los puntos), NFD también elija uno de estos (a continuación va primero, como sucede)

Las descomposiciones de compatibilidad incluyen una serie de caracteres que "en realidad no deberían ser" caracteres, pero que se deben a que se usaron en codificaciones heredadas. La normalización ordinaria no unificará esto (para preservar la integridad de ida y vuelta, esto no es un problema para las formas de combinación porque ninguna codificación heredada [excepto un puñado de codificaciones vietnamitas] utilizó ambas), pero sí la normalización de compatibilidad. Piensa como el signo del kilogramo "kg" que aparece en algunas codificaciones del este de Asia (o el katakana y alfabeto de medio ancho / ancho), o la ligadura "fi" en MacRoman.

Ver http://unicode.org/reports/tr15/ para más detalles.


El problema de comparar cadenas : dos cadenas con contenido que es equivalente a los fines de la mayoría de las aplicaciones pueden contener diferentes secuencias de caracteres.

Vea la equivalencia canónica de Unicode : si el algoritmo de comparación es simple (o debe ser rápido), la equivalencia Unicode no se realiza. Este problema ocurre, por ejemplo, en la comparación canónica XML, ver http://www.w3.org/TR/xml-c14n

Para evitar este problema ... ¿Qué estándar usar? "UTF8 expandido" o "UTF8 compacto"?
Use "ç" o "c + ◌̧."?

W3C y otros (por ejemplo, los nombres de archivo ) sugieren utilizar el "compuesto como canónico" (tenga en cuenta C de cadenas cortas "más compactas") ... Entonces,

El estándar es C ! en duda, use NFC

Para interoperabilidad, y para opciones de "convención sobre configuración" , la recomendación es el uso de NFC , para "canonizar" cadenas externas. Para almacenar XML canónico, por ejemplo, guárdelo en "FORM_C". El CSV en el grupo de trabajo web del W3C también recomienda NFC (sección 7.2).

PD: de "FORM_C" es el formulario predeterminado en la mayoría de las bibliotecas. Ex. en PHP normalizer.isnormalized () .

El término "forma de FORM_C " ( FORM_C ) se usa para ambos, para decir que "una cadena está en la forma C-canónica" (el resultado de una transformación NFC) y para decir que se usa un algoritmo transformador ... Vea http://www.macchiato.com/unicode/nfc-faq

(...) cada una de las siguientes secuencias (las dos primeras son secuencias de un solo caracter) representan el mismo caracter:

  1. U + 00C5 (Å) LETRA MAYÚSCULA LATINA A CON ANILLO ARRIBA
  2. U + 212B (Å) ANGSTROM SIGN
  3. U + 0041 (A) LETRA MAYÚSCULA LATINA A + U + 030A (̊) ANILLO COMBINADO ARRIBA

Estas secuencias se llaman canónicamente equivalentes. La primera de estas formas se llama NFC - para la Forma de Normalización C, donde la C es para composición . (...) Una función que transforma una cadena S en la forma NFC puede abreviarse como toNFC(S) , mientras que una que prueba si S está en NFC se abrevia como isNFC(S) .

Nota: para probar la normalización de pequeñas cadenas (referencias UTF-8 o entidades de XML puro), puede usar este convertidor en línea de prueba / normalización .


Esto es realmente bastante simple. UTF-8 en realidad tiene varias representaciones diferentes del mismo "personaje". (Uso el carácter entre comillas ya que byte-wise son diferentes, pero prácticamente son los mismos). Un ejemplo se da en el documento vinculado.

El carácter "Ç" se puede representar como la secuencia de bytes 0xc387. Pero también se puede representar con una C (0x43) seguida de la secuencia de bytes 0x8ccca7. Entonces puedes decir que 0xc387 y 0x438ccca7 son el mismo personaje. La razón por la que funciona, es que 0x8ccca7 es una marca de combinación; es decir, toma el carácter que tiene delante (una C aquí) y lo modifica.

Ahora, en cuanto a la diferencia entre la equivalencia canónica y la equivalencia de compatibilidad, tenemos que mirar a los personajes en general.

Hay 2 tipos de caracteres, aquellos que transmiten significado a través del valor y aquellos que toman otro carácter y lo alteran. Entonces 9 es un personaje significativo. Un superguión ⁹ toma ese significado y lo altera por presentación. Así que canónicamente tienen diferentes significados, pero aún representan el personaje base.

Entonces la equivalencia canónica es donde la secuencia de bytes está representando el mismo carácter con el mismo significado. La equivalencia de compatibilidad es cuando la secuencia de bytes está representando un carácter diferente con el mismo significado básico (aunque puede estar alterado). Entonces el 9 y ⁹ son equivalentes de compatibilidad ya que ambos significan "9", pero no son canónicamente equivalentes ya que no tienen la misma representación ...

Espero que ayude...


Las formas normales (de Unicode, no de bases de datos) tratan principalmente (¿exclusivamente?) Con caracteres que tienen signos diacríticos. Unicode proporciona algunos caracteres con signos diacríticos "incorporados", como U + 00C0, "Capital Latina A con Grave". El mismo carácter se puede crear a partir de una "Capital Latina A" (U + 0041) con una "Combinación de Acentuación Grave" (U + 0300). Eso significa que aunque las dos secuencias producen el mismo carácter resultante, un byte a byte la comparación los mostrará como completamente diferentes.

La normalización es un intento de lidiar con eso. La normalización asegura (o al menos intenta hacerlo) que todos los caracteres están codificados de la misma manera, ya sea utilizando una marca diacrítica de combinación separada donde sea necesaria, o todos utilizando un único punto de código siempre que sea posible. Desde el punto de vista de la comparación, en realidad no importa mucho lo que elija, prácticamente cualquier cadena normalizada se comparará adecuadamente con otra cadena normalizada.

En este caso, "compatibilidad" significa compatibilidad con el código que supone que un punto de código es igual a un carácter. Si tiene un código como ese, probablemente quiera usar la forma normal de compatibilidad. Aunque nunca lo he visto expuesto directamente, los nombres de las formas normales implican que el consorcio Unicode considera que es preferible usar marcas diacríticas combinadas por separado. Esto requiere más inteligencia para contar los caracteres reales en una cadena (así como cosas como romper una cuerda de forma inteligente), pero es más versátil.

Si está haciendo un uso completo de la UCI, es probable que quiera usar la forma canónica normal. Si intenta escribir código por su cuenta que (por ejemplo) asuma que un punto de código es igual a un carácter, entonces probablemente desee que la forma normal de compatibilidad lo haga verdadero tan a menudo como sea posible.


Si dos cadenas Unicode son canónicamente equivalentes, las cadenas son realmente las mismas, utilizando solo diferentes secuencias Unicode. Por ejemplo, Ä puede representarse utilizando el carácter Ä o una combinación de A y ◌̈.

Si las cadenas son solo equivalentes de compatibilidad, las cadenas no son necesariamente las mismas, pero pueden ser las mismas en algunos contextos. Por ejemplo, ff podría considerarse igual que ff.

Entonces, si está comparando cadenas, debe usar la equivalencia canónica, porque la equivalencia de compatibilidad no es la equivalencia real.

Pero si desea ordenar un conjunto de cadenas, podría ser lógico usar equivalencia de compatibilidad ya que son casi idénticas.


Si la equivalencia canónica o la equivalencia de compatibilidad es más relevante para usted depende de su aplicación. La manera ASCII de pensar en las comparaciones de cadenas se corresponde aproximadamente con la equivalencia canónica, pero Unicode representa una gran cantidad de idiomas. No creo que sea seguro suponer que Unicode codifica todos los idiomas de una manera que te permita tratarlos como ASCII europeo occidental.

Las Figuras 1 y 2 proporcionan buenos ejemplos de los dos tipos de equivalencia. Bajo la equivalencia de compatibilidad, parece que el mismo número en forma de sub script y super script se compararía igual. Pero no estoy seguro de que resuelvan el mismo problema que la forma árabe cursiva o los caracteres girados.

La dura verdad del procesamiento de texto Unicode es que debes pensar profundamente sobre los requisitos de procesamiento de texto de tu aplicación y luego abordarlos lo mejor posible con las herramientas disponibles. Eso no aborda directamente su pregunta, pero una respuesta más detallada requeriría expertos lingüísticos para cada uno de los idiomas que espera apoyar.