Lorsque j'utilise iconv pour convertir de UTF16 en UTF8, tout va bien, mais vice versa, cela ne fonctionne pas. J'ai ces fichiers:
a-16.strings: Little-endian UTF-16 Unicode c program text
a-8.strings: UTF-8 Unicode c program text, with very long lines
Le texte semble OK dans l'éditeur. Quand je lance ceci:
iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16.strings
Ensuite, j'obtiens ce résultat:
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
L'utilitaire file
n'affiche pas le format de fichier attendu et le texte ne semble pas non plus bien dans l'éditeur. Se pourrait-il que iconv ne crée pas une nomenclature appropriée? Je l'exécute sur la ligne de commande MAC.
Pourquoi le b-16 n'est-il pas au bon format UTF-16LE? Existe-t-il une autre façon de convertir utf8 en utf16?
Plus d'élaboration se trouve ci-dessous.
$ 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
Il est clair que la nomenclature est manquante chaque fois que j'exécute la conversion en UTF-16LE. Une aide à ce sujet?
UTF-16LE
indique à iconv
de générer un UTF-16 petit-boutien sans une nomenclature (Byte Order Mark). Apparemment, cela suppose que puisque vous avez spécifié LE
, la nomenclature n'est pas nécessaire.
UTF-16
lui dit de générer du texte UTF-16 (dans l'ordre des octets de la machine locale) avec une nomenclature.
Si vous êtes sur une petite machine endian, je ne vois pas de moyen de dire à iconv
de générer un UTF-16 big-endian avec une nomenclature, mais il se peut que je manque quelque chose.
Je trouve que la commande file
ne reconnaît pas le texte UTF-16 sans nomenclature, et votre éditeur ne le peut pas non plus. Mais si vous exécutez iconv -f UTF-16LE -t UTF_8 b-16 strings
, vous devriez obtenir une version UTF-8 valide du fichier d'origine.
Essayez d'exécuter od -c
sur les fichiers pour voir leur contenu réel.
MISE À JOUR:
Il semble que vous soyez sur une machine big-endian (x86 est little-endian) et que vous essayez de générer un fichier UTF-16 little-endian avec une nomenclature. Est-ce exact? Pour autant que je sache, iconv
ne le fera pas directement. Mais cela devrait fonctionner:
( printf "\xff\xfe" ; iconv -f utf-8 -t utf-16le UTF-8-FILE ) > UTF-16-FILE
Le comportement de printf
peut dépendre de vos paramètres régionaux; J'ai LANG=en_US.UTF-8
.
(Quelqu'un peut-il suggérer une solution plus élégante?)
Une autre solution de contournement, si vous connaissez l'endianité de la sortie produite par -t utf-16
:
iconv -f utf-8 -t utf-16 UTF-8-FILE | dd conv=swab 2>/dev/null
Je me convertis d'abord en UTF-16
, qui ajoutera une marque d'ordre d'octets, si nécessaire comme Keith Thompson le mentionne . Puis depuis UTF-16
ne définit pas l'endianité, nous devons utiliser file
pour déterminer si c'est UTF-16BE
ou UTF-16LE
. Enfin, nous pouvons convertir en 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
Ce n'est peut-être pas une solution élégante, mais j'ai trouvé un moyen manuel d'assurer une conversion correcte de mon problème qui, je pense, est similaire au sujet de ce fil.
Le problème: J'ai obtenu un fichier de données texte d'un utilisateur et j'allais le traiter sur Linux (spécifiquement, Ubuntu) en utilisant le script Shell (tokenisation, fractionnement, etc.). Appelons le fichier myfile.txt
. La première indication que j'ai compris que quelque chose n'allait pas était que la tokenisation ne fonctionnait pas. Je n'ai donc pas été surpris lorsque j'ai exécuté la commande file
sur myfile.txt
et a obtenu ce qui suit
$ file myfile.txt
myfile.txt: Little-endian UTF-16 Unicode text, with very long lines, with CRLF line terminators
Si le fichier était conforme, voici ce qui aurait dû être la conversation:
$ file myfile.txt
myfile.txt: ASCII text, with very long lines
La solution: Pour rendre le fichier de données conforme, voici les 3 étapes manuelles que j'ai trouvées fonctionner après quelques essais et erreurs avec d'autres étapes.
Convertissez d'abord en Big Endian avec le même encodage via vi
(ou vim
). vi myfile.txt
. Dans vi
do :set fileencoding=UTF-16BE
puis écrivez le fichier. Vous devrez peut-être le forcer avec :!wq
.
vi myfile.txt
(qui devrait maintenant être dans utf-16BE). Dans vi
do :set fileencoding=ASCII
puis écrivez le fichier. Encore une fois, vous devrez peut-être forcer l'écriture avec !wq
.
Courir dos2unix
convertisseur: d2u myfile.txt
. Si vous exécutez maintenant file myfile.txt
vous devriez maintenant voir une sortie ou quelque chose de plus familier et rassurant comme:
myfile.txt: ASCII text, with very long lines
C'est ça. C'est ce qui a fonctionné pour moi, et j'ai ensuite pu exécuter mon script shell de traitement bash de myfile.txt
. J'ai trouvé que je ne peux pas sauter l'étape 2. Autrement dit, dans ce cas, je ne peux pas passer directement à l'étape 3. J'espère que vous trouverez ces informations utiles; j'espère que quelqu'un pourra l'automatiser peut-être via sed
ou similaire. À votre santé.