delphi - ¿Qué debo usar? ¿UTF8 o UTF16?
utf-8 utf-16 (3)
Depende del idioma de tus datos.
Si sus datos están en su mayoría en idiomas occidentales y desea reducir la cantidad de almacenamiento necesario, vaya con UTF-8 ya que para esos idiomas tomará aproximadamente la mitad del almacenamiento de UTF-16. Tendrá que pagar una multa al leer los datos, ya que serán / deberán convertirse a UTF-16, que es el valor predeterminado de Windows y es utilizado por la cadena Delphi (Unicode).
Si sus datos están en su mayoría en idiomas no occidentales, UTF-8 puede tomar más almacenamiento que UTF-16, ya que puede tomar hasta 6 4 bytes por carácter para algunos. (ver comentario por @KennyTM)
Básicamente: realice algunas pruebas con muestras representativas de los datos de sus usuarios y vea cuál funciona mejor, tanto en los requisitos de almacenamiento como en los tiempos de carga. Hemos tenido algunas sorpresas con UTF-16 siendo más lento de lo que pensábamos. La ganancia de rendimiento de no tener que transformar de UTF-8 a UTF-16 se perdió debido al acceso al disco ya que el volumen de datos en UTF-16 es mayor.
Tengo que distribuir mi aplicación internacionalmente.
Digamos que tengo un control (como una nota) donde el usuario ingresa texto. El usuario puede ser japonés, ruso, canadiense, etc. Quiero guardar la cadena en el disco como archivo TXT para su uso posterior. Usaré la función MI PROPIA para escribir el texto y no algo como TMemo.SaveToFile ().
¿Cómo quiero guardar la cadena en el disco? ¿En formato UTF8 o UTF16?
En primer lugar, tenga en cuenta que la codificación estándar en Windows es UCS2 (hasta Windows 2000) o UTF-16 (desde XP), y que el tipo " string
" nativo de Delphi usa el mismo formato nativo desde Delphi 2009 ( string=UnicodeString char=WideChar
).
En todos los casos, no es seguro asumir que 1 WideChar
== 1 carácter Unicode: este es el problema del surrogate .
Sobre la elección de UTF-8 o UTF-16, depende del almacenamiento en sí mismo:
- Si su archivo es un archivo de texto plano (incluido XML), puede usar UTF-8 o UTF-16, pero tendrá que usar una lista de materiales al comienzo del archivo, de lo contrario las aplicaciones (como el Bloc de notas) pueden confundirse al abrir - para XML, esto lo maneja su biblioteca (si no lo es, cambie a otra biblioteca);
- Si está seguro de que su contenido es principalmente de ASCII de 7 bits, utilice UTF-8 y la lista de materiales asociada;
- Si su archivo es algún tipo de base de datos o un formato binario personalizado, ciertamente el mejor formato es UTF-16 / UCS2, es decir, el diseño de
string
predeterminado de Delphi 2009+, y ciertamente el diseño de API de base de datos predeterminado; - Algunos formatos de archivo requieren o prefieren UTF-8 (como JSON o incluso SQLite3 ), incluso si los archivos UTF-8 pueden ser más grandes que UTF-16 para los caracteres asiáticos.
Por ejemplo, usamos UTF-8 para nuestro marco Cliente-Servidor, ya que usamos JSON como formato de intercambio (que requiere UTF-8), y como a SQlite3 le gusta UTF-8. Por supuesto, tuvimos que escribir algunas funciones y clases dedicadas, para evitar la conversión a / desde la string
(que es lenta para el tipo string=UnicodeString
desde Delphi 2009, y puede perder algunos datos cuando se usa con el tipo string=AnsiString
antes de Delphi 2009. Ver este post y esta unidad ). Lo más fácil es confiar en el tipo string=UnicodeString
, usar las funciones RTL que manejan directamente la codificación UTF-16 y evitar conversiones. Y no te olvides de tu pregunta anterior .
Si el espacio en disco y la velocidad de lectura / escritura son un problema, considere usar la compresión en lugar de cambiar la codificación. Hay compresión en tiempo real (más rápido que ZIP), como LZO o nuestro SynLZ.
La principal diferencia entre ellos es que UTF8 es compatible con ASCII. Siempre y cuando solo use los primeros 128 caracteres, una aplicación que no sea compatible con Unicode puede procesar los datos (lo que puede ser una ventaja o una desventaja, según su situación). En particular, cuando se cambia a UTF16, cada función de API debe ajustarse para cadenas de 16 bits, mientras que con UTF8 a menudo puede dejar intactas las funciones de API antiguas si no realizan ningún procesamiento de cadenas. Además, UTF8 no depende de la endianess, mientras que UTF16 sí lo hace, lo que puede complicar la E / S de cadena.
Un error común es que es más fácil procesar UTF16 porque cada carácter siempre ocupa exactamente dos bytes. Eso es, desafortunadamente, no es cierto. UTF16 es una codificación de longitud variable en la que un carácter puede ocupar 2 o 4 bytes. Por lo tanto, cualquier dificultad asociada con UTF8 con respecto a los problemas de longitud variable se aplica también a UTF16.
Finalmente, tamaños de almacenamiento: otro mito común acerca de UTF16 es que es más eficiente en almacenamiento que UTF8 para la mayoría de los idiomas extranjeros. UTF8 requiere menos almacenamiento para todos los idiomas europeos, que pueden codificarse con uno o dos bytes por carácter. Los caracteres que no son BMP ocupan 4 bytes tanto en UTF8 como en UTF16. El único caso en el que UTF16 requiere menos almacenamiento es si su texto consiste principalmente en caracteres del rango U + 0800 a U + FFFF, donde se almacenan los caracteres para chino, japonés e hindi.
James McNellis dio una excelente charla en BoostCon 2014, en la que habló sobre los diversos compromisos entre las diferentes codificaciones con gran detalle. A pesar de que la charla se titula Unicode en C ++ , la primera mitad completa es en realidad agnóstica. Una grabación de video de la charla completa está disponible en el canal de Youtube de Boostcon , mientras que las diapositivas se pueden encontrar en github .