Iconvを使用してUTF16からUTF8に変換すると、すべては問題ありませんが、その逆は機能しません。これらのファイルがあります:
a-16.strings: Little-endian UTF-16 Unicode c program text
a-8.strings: UTF-8 Unicode c program text, with very long lines
テキストはエディターでOKに見えます。これを実行すると:
iconv -f UTF-8 -t UTF-16LE a-8.strings > b-16.strings
次に、この結果が得られます:
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
file
ユーティリティは、期待されるファイル形式を表示せず、テキストもエディターで適切に表示されません。 iconvが適切なBOMを作成しないのでしょうか? MACコマンドラインで実行します。
なぜb-16は適切なUTF-16LE形式ではないのですか? utf8をutf16に変換する別の方法はありますか?
さらに詳しく説明します。
$ 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
UTF-16LEへの変換を実行するたびにBOMが欠落していることは明らかです。これについて何か助けがありますか?
UTF-16LE
は、リトルエンディアンUTF-16withoutBOM(バイトオーダーマーク)を生成するようiconv
に指示します。 LE
を指定したため、BOMは必要ないと思われます。
UTF-16
は、(ローカルマシンのバイトオーダーで)UTF-16テキストを生成するように指示しますwithBOM。
リトルエンディアンのマシンを使用している場合、iconv
にBOMを使用してビッグエンディアンUTF-16を生成するように指示する方法はありませんが、何か不足している可能性があります。
file
コマンドはBOMなしのUTF-16テキストを認識せず、エディターもそうでない可能性があります。ただし、iconv -f UTF-16LE -t UTF_8 b-16 strings
を実行する場合は、元のファイルの有効なUTF-8バージョンを取得する必要があります。
ファイルでod -c
を実行して、実際の内容を確認してください。
PDATE:
ビッグエンディアンのマシン(x86はリトルエンディアン)で、BOMを使用してリトルエンディアンUTF-16ファイルを生成しようとしているようです。あれは正しいですか?私が知る限り、iconv
はそれを直接行いません。しかし、これは動作するはずです:
( printf "\xff\xfe" ; iconv -f utf-8 -t utf-16le UTF-8-FILE ) > UTF-16-FILE
printf
mightの動作は、ロケール設定に依存します。 LANG=en_US.UTF-8
があります。
(誰もがよりエレガントなソリューションを提案できますか?)
別の回避策、if-t utf-16
によって生成される出力のエンディアンを知っている場合:
iconv -f utf-8 -t utf-16 UTF-8-FILE | dd conv=swab 2>/dev/null
最初にUTF-16
に変換します。これは、必要に応じてバイト順マークを付加します Keith Thompsonが述べているように 。 UTF-16
はエンディアンを定義しないため、file
を使用して、UTF-16BE
かUTF-16LE
かを判断する必要があります。最後に、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
これはエレガントな解決策ではないかもしれませんが、このスレッドの主題に似ていると思われる私の問題の正しい変換を確実にするための手動の方法を見つけました。
問題:ユーザーからテキストデータファイルを取得し、シェルスクリプト(トークン化、分割など)を使用してLinux(具体的にはUbuntu)で処理します。ファイルをmyfile.txt
と呼びましょう。何かがおかしいとわかった最初の兆候は、トークン化が機能していなかったことです。 myfile.txt
でfile
コマンドを実行して次のようになったとき、私は驚きませんでした
$ file myfile.txt
myfile.txt: Little-endian UTF-16 Unicode text, with very long lines, with CRLF line terminators
ファイルが準拠している場合、会話は次のようになります。
$ file myfile.txt
myfile.txt: ASCII text, with very long lines
解決策:データファイルを準拠させるために、他の手順で試行錯誤を繰り返した結果、3つの手動手順が機能することがわかりました。
最初に、vi
(またはvim
)を介して同じエンコーディングでビッグエンディアンに変換します。 vi myfile.txt
。 vi
で:set fileencoding=UTF-16BE
を実行し、ファイルを書き出します。 :!wq
で強制する必要があるかもしれません。
vi myfile.txt
(utf-16BEになりました)。 vi
で:set fileencoding=ASCII
を実行し、ファイルを書き出します。繰り返しますが、!wq
を使用して書き込みを強制する必要がある場合があります。
dos2unix
コンバーターを実行します:d2u myfile.txt
。 file myfile.txt
を実行すると、出力が表示されるか、より身近で確実なものが表示されるはずです。
myfile.txt: ASCII text, with very long lines
それでおしまい。それが私にとってはうまくいったので、myfile.txt
の処理bashシェルスクリプトを実行することができました。ステップ2をスキップできないことがわかりました。つまり、この場合、ステップ3に直接スキップすることはできません。この情報が役立つことを願っています。おそらくsed
などを介して誰かがそれを自動化できることを願っています。乾杯。