linux - txt - convertir texto a utf-8 online
Convertir UTF8 a UTF16 usando iconv (3)
Primero convierto a UTF-16
, que antepondrá una marca de orden de bytes, si es necesario, como menciona Keith Thompson . Luego, dado que UTF-16
no define la endianidad, debemos usar el file
para determinar si es UTF-16BE
o UTF-16LE
. Finalmente, podemos convertir a UTF-16LE
.
iconv -f utf-8 -t utf-16 UTF-8-FILE > UTF-16-UNKNOWN-ENDIANNESS-FILE
FILE_ENCODING="$( file --brief --mime-encoding UTF-16-UNKNOWN-ENDIANNESS-FILE )"
iconv -f "$FILE_ENCODING" -t UTF-16LE UTF-16-UNKNOWN-ENDIANNESS-FILE > UTF-16-FILE
Cuando uso iconv para convertir de UTF16 a UTF8, entonces todo está bien, pero viceversa, no funciona. Tengo estos archivos:
a-16.strings: Little-endian UTF-16 Unicode c program text
a-8.strings: UTF-8 Unicode c program text, with very long lines
El texto se ve bien en el editor. Cuando corro esto:
iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16.strings
Entonces me sale este resultado:
b-16.strings: data
a-16.strings: Little-endian UTF-16 Unicode c program text
a-8.strings: UTF-8 Unicode c program text, with very long lines
La utilidad de file
no muestra el formato de archivo esperado y el texto tampoco se ve bien en el editor. ¿Podría ser que iconv no crea una lista de materiales adecuada? Lo ejecuto en la línea de comandos de MAC.
¿Por qué el b-16 no está en el formato UTF-16LE adecuado? ¿Hay otra manera de convertir utf8 a utf16?
Más elaboración está abajo.
$ iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16le-BAD-fromUTF8.strings
$ iconv -f UTF-8 -t UTF-16 a-8.strings > b-16be.strings
$ iconv -f UTF-16 -t UTF-16LE b-16be.strings > b-16le-BAD-fromUTF16BE.strings
$ file *s
a-16.strings: Little-endian UTF-16 Unicode c program text, with very long lines
a-8.strings: UTF-8 Unicode c program text, with very long lines
b-16be.strings: Big-endian UTF-16 Unicode c program text, with very long lines
b-16le-BAD-fromUTF16BE.strings: data
b-16le-BAD-fromUTF8.strings: data
$ od -c a-16.strings | head
0000000 377 376 / /0 * /0 /0 /f 001 E /0 S /0 K /0
$ od -c a-8.strings | head
0000000 / * * * Č ** E S K Y ( J V O
$ od -c b-16be.strings | head
0000000 376 377 /0 / /0 * /0 * /0 * /0 001 /f /0 E
$ od -c b-16le-BAD-fromUTF16BE.strings | head
0000000 / /0 * /0 * /0 * /0 /0 /f 001 E /0 S /0
$ od -c b-16le-BAD-fromUTF8.strings | head
0000000 / /0 * /0 * /0 * /0 /0 /f 001 E /0 S /0
Está claro que falta la lista de materiales cuando ejecuto la conversión a UTF-16LE. ¿Alguna ayuda en esto?
Puede que esta no sea una solución elegante, pero encontré una forma manual para asegurar la conversión correcta para mi problema que creo que es similar al tema de este hilo.
El problema: obtuve un archivo de datos de texto de un usuario y lo iba a procesar en Linux (específicamente, Ubuntu) usando un script de shell (tokenización, división, etc.). Llamemos al archivo myfile.txt
. La primera indicación de que entendí que algo estaba mal era que la tokenización no estaba funcionando. Así que no me sorprendió cuando ejecuté el comando de file
en myfile.txt
y obtuve lo siguiente
$ file myfile.txt
myfile.txt: Little-endian UTF-16 Unicode text, with very long lines, with CRLF line terminators
Si el archivo era compatible, esto es lo que debería haber sido la conversación:
$ file myfile.txt
myfile.txt: ASCII text, with very long lines
La solución: para hacer que el archivo de datos sea compatible, a continuación se encuentran los 3 pasos manuales que encontré para funcionar después de algunas pruebas y errores con otros pasos.
Primero convierta a Big Endian en la misma codificación a través de
vi
(ovim
).vi myfile.txt
. Envi
do:set fileencoding=UTF-16BE
luego escriba el archivo. Puede que tenga que forzarlo con:!wq
.vi myfile.txt
(que ahora debería estar en utf-16BE). Envi
do:set fileencoding=ASCII
luego escriba el archivo. De nuevo, puede que tengas que forzar la escritura con!wq
.Ejecute el convertidor
dos2unix
:d2u myfile.txt
. Si ahora ejecuta elfile myfile.txt
, ahora debería ver una salida o algo más familiar y seguro como:myfile.txt: ASCII text, with very long lines
Eso es. Eso fue lo que funcionó para mí, y luego pude ejecutar mi script bash de procesamiento de myfile.txt
. Descubrí que no puedo omitir el Paso 2. Es decir, en este caso no puedo saltar directamente al Paso 3. Esperamos que esta información sea útil; Esperemos que alguien pueda automatizarlo quizás a través de sed
o similar. Aclamaciones.
UTF-16LE
le dice a iconv
que genere un little endian UTF-16 sin una lista de materiales (marca de orden de bytes). Aparentemente asume que, dado que especificó LE
, la lista de materiales no es necesaria.
UTF-16
le dice que genere texto UTF-16 (en el orden de bytes de la máquina local) con una lista de materiales.
Si estás en una máquina little-endian, no veo una manera de decirle a iconv
que genere un UTF-16 big-endian con un BOM, pero es posible que solo me esté perdiendo algo.
Me parece que el comando de file
no reconoce el texto UTF-16 sin una lista de materiales, y su editor tampoco puede. Pero si ejecuta iconv -f UTF-16LE -t UTF_8 b-16 strings
, debe obtener una versión válida de UTF-8 del archivo original.
Intente ejecutar od -c
en los archivos para ver su contenido real.
ACTUALIZACIÓN:
Parece que estás en una máquina big-endian (x86 es little-endian), e intentas generar un archivo UTF-16 little-endian con una lista de materiales. ¿Es eso correcto? Por lo que puedo decir, iconv
no lo hará directamente. Pero esto debería funcionar:
( printf "/xff/xfe" ; iconv -f utf-8 -t utf-16le UTF-8-FILE ) > UTF-16-FILE
El comportamiento de printf
puede depender de su configuración regional; Tengo LANG=en_US.UTF-8
.
(¿Alguien puede sugerir una solución más elegante?)
Otra solución, si conoce el carácter endiano de la salida producida por -t utf-16
:
iconv -f utf-8 -t utf-16 UTF-8-FILE | dd conv=swab 2>/dev/null