ver utf8 convertir change utf-8 character-encoding iconv

utf 8 - utf8 - Forzar la codificación de US-ASCII a UTF-8(iconv)



utf 8 linux (7)

Estoy tratando de transcodificar un montón de archivos de US-ASCII a UTF-8.

Para eso, estoy usando iconv:

iconv -f US-ASCII -t UTF-8 file.php > file-utf8.php

La cosa es que mis archivos originales están codificados en US-ASCII, lo que hace que la conversión no ocurra. Aparentemente ocurre porque ASCII es un subconjunto de UTF-8 ...

http://www.linuxquestions.org/questions/linux-software-2/iconv-us-ascii-to-utf-8-or-iso-8859-15-a-705054/

Y citando:

No es necesario que el archivo de texto aparezca de otra manera hasta que se introduzcan caracteres que no sean ASCII

Cierto. Si introduzco un carácter no ASCII en el archivo y lo guardo, digamos que con Eclipse, la codificación del archivo (conjunto de caracteres) se cambia a UTF-8.

En mi caso, me gustaría forzar a iconv a transcodificar los archivos a UTF-8 de todos modos . Si hay caracteres no ASCII en él o no.

Nota: la razón es que mi código PHP (archivos no ASCII ...) trata con una cadena que no es ASCII, lo que hace que las cadenas no se interpreten bien (francés):

Il ê tait une fois ... l''homme série animée mythique d''Albert

Barillé (Procidis), 1ère

...

EDITAR

  • US-ASCII - es - un subconjunto de UTF-8 (vea la respuesta de Ned a continuación)
  • Lo que significa que US-ASCII archivos US-ASCII realidad están codificados en UTF-8
  • Mi problema vino de otro lado

Respuesta corta

  • file solo adivina la codificación del archivo y puede estar equivocado (especialmente en los casos en que los caracteres especiales solo aparecen tarde en los archivos grandes).
  • puede usar hexdump para ver bytes de texto no-7-bit-ascii y comparar con tablas de códigos para codificaciones comunes (iso-8859- *, utf-8) para decidir cuál es la codificación.
  • iconv utilizará la codificación de entrada / salida que especifique, independientemente del contenido del archivo. Si especifica la codificación de entrada incorrecta, la salida será confusa.
  • Incluso después de ejecutar iconv , es posible que el file no informe ningún cambio debido a la forma limitada en que el file intenta adivinar la codificación. Para un ejemplo específico, vea mi respuesta larga.
  • Ascii de 7 bits (también conocido como us-ascii) es idéntico a nivel de byte a utf-8 y las extensiones de ascii de 8 bits (iso-8859- *). Entonces, si su archivo solo tiene caracteres de 7 bits, entonces puede llamarlo utf-8, iso-8859- * o us-ascii porque a nivel de byte todos son idénticos. Solo tiene sentido hablar de utf-8 y otras codificaciones (en este contexto) una vez que su archivo tenga caracteres fuera del rango de ascii de 7 bits.

Respuesta larga

Me encontré con esto hoy y me encontré con su pregunta. Quizás pueda agregar un poco más de información para ayudar a otras personas que tienen este problema.

Primero, el término ASCII está sobrecargado, y eso lleva a confusión.

El ASCII de 7 bits solo incluye 128 caracteres (00-7F o 0-127 en decimal). ASCII de 7 bits también se conoce como US-ASCII.

https://en.wikipedia.org/wiki/ASCII

La codificación UTF-8 utiliza la misma codificación que ASCII de 7 bits para sus primeros 128 caracteres. Por lo tanto, un archivo de texto que solo contenga caracteres de ese rango de los primeros 128 caracteres será idéntico a nivel de byte, ya sea codificado con UTF-8 o ASCII de 7 bits.

https://en.wikipedia.org/wiki/UTF-8#Codepage_layout

El término ascii extendido (o alto ascii ) se refiere a codificaciones de caracteres de ocho bits o más que incluyen los caracteres ASCII estándar de siete bits, más caracteres adicionales.

https://en.wikipedia.org/wiki/Extended_ASCII

ISO-8859-1 (también conocido como "ISO Latin 1") es un estándar específico de extensión ASCII de 8 bits que cubre la mayoría de los caracteres para Europa occidental. Existen otras normas ISO para los idiomas de Europa del Este y los idiomas cirílicos. ISO-8859-1 incluye caracteres como Ö, é, ñ y ß para alemán y español. "Extensión" significa que ISO-8859-1 incluye el estándar ASCII de 7 bits y le agrega caracteres utilizando el octavo bit. Por lo tanto, para los primeros 128 caracteres, es equivalente a nivel de byte a los archivos codificados en ASCII y UTF-8. Sin embargo, cuando comienza a tratar con caracteres más allá de los primeros 128, ya no son equivalentes a UTF-8 en el nivel de byte, y debe hacer una conversión si desea que su archivo "ascii extendido" esté codificado en UTF-8.

https://en.wikipedia.org/wiki/Extended_ASCII#ISO_8859_and_proprietary_adaptations

Una lección que aprendí hoy es que no podemos confiar en que el file siempre dé una interpretación correcta de la codificación de caracteres de un archivo.

https://en.wikipedia.org/wiki/File_%28command%29

El comando solo indica cómo se ve el archivo, no cómo es (en el caso de que el archivo mire el contenido). Es fácil engañar al programa al poner un número mágico en un archivo cuyo contenido no coincide. Por lo tanto, el comando no se puede utilizar como una herramienta de seguridad más que en situaciones específicas.

file busca números mágicos en el archivo que indiquen el tipo, pero estos pueden ser incorrectos, sin garantía de corrección. file también intenta adivinar la codificación de caracteres mirando los bytes en el archivo. Básicamente, el file tiene una serie de pruebas que lo ayudan a adivinar el tipo de archivo y la codificación.

Mi archivo es un archivo CSV grande. file reporta este archivo como us-ascii codificado, que es MAL .

$ ls -lh total 850832 -rw-r--r-- 1 mattp staff 415M Mar 14 16:38 source-file $ file -b --mime-type source-file text/plain $ file -b --mime-encoding source-file us-ascii

Mi archivo tiene diéresis en él (es decir, Ö). El primer ascii que no es de 7 bits no aparece hasta más de 100k líneas en el archivo. Sospecho que es por eso que el file no se da cuenta de que la codificación del archivo no es US-ASCII.

$ pcregrep -no ''[^/x00-/x7F]'' source-file | head -n1 102321:�

Estoy en un mac, así que uso grep de PCRE. Con gnu grep puede usar la opción -P . Alternativamente, en una mac, uno podría instalar coreutils (a través de homebrew u otro) para obtener gnu grep.

No he buscado en el código fuente del file , y la página de manual no analiza en detalle la detección de codificación de texto, pero supongo que el file no se ve en todo el archivo antes de adivinar la codificación.

Cualquiera que sea la codificación de mi archivo, estos caracteres ASCII que no son de 7 bits rompen cosas. Mi archivo CSV alemán es ; -separa y la extracción de una sola columna no funciona.

$ cut -d";" -f1 source-file > tmp cut: stdin: Illegal byte sequence $ wc -l * 3081673 source-file 102320 tmp 3183993 total

Tenga en cuenta el error de cut y que mi archivo "tmp" tiene solo 102320 líneas con el primer carácter especial en la línea 102321.

Veamos cómo se codifican estos caracteres que no son ASCII. Vuelvo los primeros ascii que no son de 7 bits en hexdump , hago un pequeño formateo, elimino las nuevas líneas ( 0a ) y tomo solo las primeras.

$ pcregrep -o ''[^/x00-/x7F]'' source-file | head -n1 | hexdump -v -e ''1/1 "%02x/n"'' d6 0a

De otra manera. Sé que el primer char no ASCII de 7 bits está en la posición 85 en la línea 102321. Tomo esa línea y le hexdump a hexdump que tome los dos bytes que comienzan en la posición 85. Puede ver el especial (no ASCII de 7 bits) ) carácter representado por un ".", y el siguiente byte es "M" ... por lo que esta es una codificación de caracteres de un solo byte.

$ tail -n +102321 source-file | head -n1 | hexdump -C -s85 -n2 00000055 d6 4d |.M| 00000057

En ambos casos, vemos que el carácter especial está representado por d6 . Dado que este carácter es un Ö que es una letra alemana, supongo que ISO-8859-1 debería incluir esto. Por supuesto, puedes ver que "d6" es una coincidencia ( https://en.wikipedia.org/wiki/ISO/IEC_8859-1#Codepage_layout ).

Pregunta importante ... ¿cómo sé que este carácter es un Ö sin estar seguro de la codificación del archivo? La respuesta es contexto. Abrí el archivo, leí el texto y luego determiné qué carácter se supone que debe ser. Si lo abro en vim se muestra como un Ö porque vim hace un mejor trabajo de adivinar la codificación de caracteres (en este caso) que el file .

Por lo tanto, mi archivo parece ser ISO-8859-1. En teoría, debería verificar el resto de los caracteres ASCII que no son de 7 bits para asegurarme de que ISO-8859-1 sea un buen ajuste ... No hay nada que obligue a un programa a usar solo una codificación al escribir un archivo para disco (excepto buenos modales).

Me saltearé el cheque y pasaré al paso de conversión.

$ iconv -f iso-8859-1 -t utf8 source-file > output-file $ file -b --mime-encoding output-file us-ascii

Hmm file aún me dice que este archivo es US-ASCII incluso después de la conversión. Vamos a comprobarlo con hexdump nuevamente.

$ tail -n +102321 output-file | head -n1 | hexdump -C -s85 -n2 00000055 c3 96 |..| 00000057

Definitivamente un cambio. Tenga en cuenta que tenemos dos bytes de ASCII sin 7 bits (representado por el "." A la derecha) y el código hexadecimal para los dos bytes ahora es c3 96 . Si echamos un vistazo, parece que ahora tenemos UTF-8 (c3 96 es la codificación correcta de Ö en UTF-8) http://www.utf8-chartable.de/

Pero el file sigue reportando nuestro archivo como us-ascii ? Bueno, creo que esto se remonta al punto de que el file no mira todo el archivo y el hecho de que los primeros caracteres ASCII que no son de 7 bits no aparecen hasta lo más profundo del archivo.

sed para pegar un Ö al principio del archivo y ver qué pasa.

$ sed ''1s/^/Ö/'$''/n/'' source-file > test-file $ head -n1 test-file Ö $ head -n1 test-file | hexdump -C 00000000 c3 96 0a |...| 00000003

Genial, tenemos una diéresis. Tenga en cuenta que la codificación es c3 96 (utf-8). Hmm

Comprobando nuestras otras diéresis en el mismo archivo otra vez:

$ tail -n +102322 test-file | head -n1 | hexdump -C -s85 -n2 00000055 d6 4d |.M| 00000057

ISO-8859-1. Ups! Solo sirve para mostrar lo fácil que es arruinar las codificaciones.

Intentemos convertir nuestro nuevo archivo de prueba con la diéresis en la parte delantera y ver qué pasa.

$ iconv -f iso-8859-1 -t utf8 test-file > test-file-converted $ head -n1 test-file-converted | hexdump -C 00000000 c3 83 c2 96 0a |.....| 00000005 $ tail -n +102322 test-file-converted | head -n1 | hexdump -C -s85 -n2 00000055 c3 96 |..| 00000057

Ups. Esa primera diéresis que fue UTF-8 fue interpretada como ISO-8859-1 ya que eso es lo que le dijimos a iconv . La segunda diéresis se convierte correctamente de d6 a c3 96 .

Intentaré nuevamente, esta vez vim para hacer la inserción Ö en lugar de sed . vim pareció detectar mejor la codificación (como "latin1", también conocida como ISO-8859-1), por lo que quizás inserte el nuevo Ö con una codificación consistente.

$ vim source-file $ head -n1 test-file-2 � $ head -n1 test-file-2 | hexdump -C 00000000 d6 0d 0a |...| 00000003 $ tail -n +102322 test-file-2 | head -n1 | hexdump -C -s85 -n2 00000055 d6 4d |.M| 00000057

Se ve bien. Parece ISO-8859-1 para diéresis nuevas y viejas.

Ahora la prueba.

$ file -b --mime-encoding test-file-2 iso-8859-1 $ iconv -f iso-8859-1 -t utf8 test-file-2 > test-file-2-converted $ file -b --mime-encoding test-file-2-converted utf-8

¡Auge! Moraleja de la historia. No confíe en el file para adivinar siempre su derecho de codificación. Fácil de mezclar codificaciones dentro del mismo archivo. En caso de duda, mira el hex.

Un truco (que también es propenso a fallar) que solucionaría esta limitación específica del file al tratar con archivos grandes sería acortar el archivo para asegurarse de que aparezcan caracteres especiales al principio del archivo, por lo file es más probable que el archivo los encuentre.

$ first_special=$(pcregrep -o1 -n ''()[^/x00-/x7F]'' source-file | head -n1 | cut -d":" -f1) $ tail -n +$first_special source-file > /tmp/source-file-shorter $ file -b --mime-encoding /tmp/source-file-shorter iso-8859-1

Actualizar

Christos Zoulas actualizó el file para hacer que la cantidad de bytes parecida configurable. ¡Un día de vuelta en la solicitud de características, impresionante!

http://bugs.gw.com/view.php?id=533 https://github.com/file/file/commit/d04de269e0b06ccd0a7d1bf4974fed1d75be7d9e

La característica fue lanzada en file versión de file 5.26.

Mirar más de un archivo grande antes de hacer una conjetura sobre la codificación lleva tiempo. Sin embargo, es bueno tener la opción para casos de uso específicos donde una mejor suposición puede ser mayor que el tiempo / io adicional.

Utilice la siguiente opción:

−P, −−parameter name=value Set various parameter limits. Name Default Explanation bytes 1048576 max number of bytes to read from file

Algo como...

file_to_check="myfile" bytes_to_scan=$(wc -c < $file_to_check) file -b --mime-encoding -P bytes=$bytes_to_scan $file_to_check

... debería hacer el truco si quiere forzar el file para que vea todo el archivo antes de hacer una conjetura. Por supuesto, esto solo funciona si tiene el file 5.26 o más reciente.

No he construido / probado los últimos lanzamientos todavía. La mayoría de mis máquinas actualmente tienen el file 5.04 (2010) ... ojalá algún día esta versión salga del flujo ascendente.


ASCII es un subconjunto de UTF-8, por lo que todos los archivos ASCII ya están codificados en UTF-8. Los bytes en el archivo ASCII y los bytes que resultarían de "codificarlo a UTF-8" serían exactamente los mismos bytes. No hay diferencia entre ellos, así que no hay necesidad de hacer nada.

Parece que su problema es que los archivos no son en realidad ASCII. Debe determinar qué codificación están utilizando y transcodificarlos correctamente.


Aquí hay una secuencia de comandos que encontrará todos los archivos que coincidan con un patrón que usted pasa, y luego los convierte de su codificación de archivo actual a utf-8. Si la codificación es us-ascii, seguirá apareciendo como us-ascii, ya que es un subconjunto de utf-8.

#!/usr/bin/env bash find . -name "${1}" | while read line; do echo "***************************" echo "Converting ${line}" encoding=$(file -b --mime-encoding ${line}) echo "Found Encoding: ${encoding}" iconv -f "${encoding}" -t "utf-8" ${line} -o ${line}.tmp mv ${line}.tmp ${line} done


Creo que Ned tiene el núcleo del problema : sus archivos no son en realidad ASCII. Tratar

iconv -f ISO-8859-1 -t UTF-8 file.php > file-utf8.php

Supongo que en realidad estás usando iso-8859-1 , es popular en la mayoría de los idiomas europeos.


Entonces, la gente dice que no puedes y entiendo que puedes sentirte frustrado cuando haces una pregunta y recibes esa respuesta.

Si realmente quieres que se muestre en utf-8 en lugar de us-ascii, debes hacerlo en 2 pasos.

primero :

iconv -f us-ascii -t utf-16 yourfile > youfileinutf16.*

segundo:

iconv -f utf-16le -t utf-8 yourfileinutf16 > yourfileinutf8.*

entonces si haces un archivo -i verás que el nuevo conjunto de caracteres es utf-8.

Espero eso ayude.


No hay diferencia entre US-ASCII y UTF-8, por lo que no es necesario reconvertirlo. Pero aquí un pequeño consejo, si tiene problemas con caracteres especiales mientras recodifica.

Agregue // TRANSLIT después de la fuente-charset-Parameter.

Ejemplo:

iconv -f ISO-8859-1//TRANSLIT -t UTF-8 filename.sql > utf8-filename.sql

Esto me ayuda en tipos extraños de citas, que siempre rompieron el proceso de recodificación de caracteres.


Puede usar el file -i file_name para verificar cuál es exactamente su formato de archivo original.

Una vez que obtenga eso, puede hacer lo siguiente:

iconv -f old_format -t utf-8 input_file -o output_file