2012-01-19 44 views
22

Cuando uso iconv para convertir de UTF16 a UTF8 todo está bien, pero viceversa, no funciona. que tienen estos archivos:Convierta UTF8 a UTF16 con iconv

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 mirar bien en el editor. Cuando ejecuto esto:

iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16.strings 

Entonces consigo 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 file no muestra el formato de archivo esperada y el texto no se ve bien en el editor tampoco. ¿Podría ser que iconv no crea la lista de materiales adecuada? Lo ejecuto en la línea de comando MAC.

¿Por qué el b-16 no está en el formato UTF-16LE correcto? ¿Hay alguna otra forma de convertir utf8 a utf16?

Más elaboración está por debajo.

$ 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 cada vez que ejecuto la conversión a UTF-16LE. ¿Alguna ayuda en esto?

+0

lo que si se ha utilizado 'iconv -f UTF-8 UTF-16LE -t a-b-8.strings -o 16.strings' en su lugar? Dudo que lo arregle, pero vale la pena intentarlo. – cha0site

+0

mi versión de iconv no admite el parámetro -o (MacOS). Como dijiste, probablemente no ayudaría. Gracias por probar de todos modos. –

+0

Su salida muestra 'iconv -f UTF-8 -t UTF-16 a-8.strings' (se ejecuta en un sistema little-endian) generando un UTF-16 de gran tamaño con una BOM. ¿Puedes confirmar eso? ¿El comando 'iconv' de MacOS funciona de manera diferente que el de Linux? 'echo hola | iconv -f ascii -t UTF-16 | od -x' –

Respuesta

31

UTF-16LE dice iconv para generar ascendente hacia la izquierda UTF-16 sin un BOM (Byte Order Mark). Aparentemente, se supone que ya 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 BOM.

Si está en una máquina little-endian, no veo la forma de decirle a iconv que genere un UTF-16 de big-endian con una BOM, pero podría estar perdiendo algo.

Me parece que el comando file no reconoce el texto UTF-16 sin una lista de materiales, y es posible que el editor tampoco lo haga. Pero si ejecuta iconv -f UTF-16LE -t UTF_8 b-16 strings, debe obtener una versión UTF-8 válida del archivo original.

Pruebe ejecutar od -c en los archivos para ver sus contenidos reales.

ACTUALIZACIÓN:

Parece que estás en una máquina-big endian (x86 es ascendente hacia la izquierda), y que está tratando de generar un archivo poco-endian UTF-16 con una lista de materiales . ¿Es eso correcto? Por lo que puedo decir, iconv no hará eso 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 la fuerza printf dependen de los valores de localización; Tengo LANG=en_US.UTF-8.

(¿Alguien puede sugerir una solución más elegante?)

Otra solución, si se conoce el orden de bits de la salida producida por -t utf-16:

iconv -f utf-8 -t utf-16 UTF-8-FILE | dd conv=swab 2>/dev/null 
+0

Gracias Keith por ayuda. He editado mi pregunta original con más resultados según su ayuda. ¿Sabrías cómo solucionarlo? ¿Qué pasa si simplemente coloco la BOM allí manualmente? –

+0

Ver respuesta actualizada. –

+0

También estoy en una máquina basada en Intel pero ejecutando MacOS. No obstante, la adición manual de la lista de materiales como ha propuesto funciona muy bien. ¡Muchas gracias! –

0

esto puede no ser una solución elegante, pero me pareció una forma manual para asegurar una conversión correcta para mi problema que Creo que es similar al tema de este hilo.

El problema: Tengo un archivo de datos de texto desde un usuario y que iba a procesarlo en Linux (en concreto, Ubuntu) utilizando script de shell (tokenización, división, etc.). Llamemos al archivo myfile.txt. La primera indicación de que entendí que algo andaba mal fue que la tokenización no funcionaba. Así que no me sorprendió cuando me encontré con el comando file en myfile.txt y obtuve el 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 que el archivo de datos sea compatible, a continuación se detallan los 3 pasos manuales que encontré que funcionan después de algunos intentos de prueba y error con otros pasos.

  1. primer convertido a Big Endian en la misma codificación a través de vi (o vim). vi myfile.txt. En vi haga :set fileencoding=UTF-16BE luego escriba el archivo. Es posible que tenga que forzarlo con :!wq.

  2. vi myfile.txt (que ahora debería estar en utf-16BE). En vi haga :set fileencoding=ASCII luego escriba el archivo. Nuevamente, puede forzar la escritura con !wq.

  3. Ejecute dos2unix convertidor: d2u myfile.txt. Si ahora ejecuta file myfile.txt debería ver ahora una salida o algo más familiar y asegurando así:

    myfile.txt: ASCII text, with very long lines 
    

Eso es todo. Eso es lo que funcionó para mí, y luego pude ejecutar mi secuencia de comandos bash shell de procesamiento de myfile.txt. Descubrí que no puedo omitir el Paso 2. Es decir, en este caso no puedo pasar directamente al Paso 3. Espero que pueda encontrar útil esta información; esperemos que alguien pueda automatizarlo tal vez a través del sed o similar. Aclamaciones.

3

Primero convierto a UTF-16, lo que antecederá a una marca de orden de bytes, si es necesario as Keith Thompson mentions. Entonces, dado que UTF-16 no define endianness, debemos usar 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