3

次の問題を検討してください。

複数行の文字列$junkには、UTF-8 でエンコードされた行と ISO-8859-1 でエンコードされた行が含まれています。どの行がどのエンコーディングに含まれているかはアプリオリにわからないため、ヒューリスティックが必要になります。

$junkISO-8859-1 行を適切に再エンコードして、純粋な UTF-8 に変換したいと考えています。また、処理中にエラーが発生した場合は、エラーをスローするのではなく、「ベスト エフォートの結果」を提供したいと考えています。

私の現在の試みは次のようになります。

$junk = force_utf8($junk);

sub force_utf8 {
  my $input = shift;
  my $output = '';
  foreach my $line (split(/\n/, $input)) {
    if (utf8::valid($line)) {
      utf8::decode($line);
    }
    $output .= "$line\n";
  }
  return $output;
}

各行の元のエンコーディングに関する情報が不足しているため、変換が完全に行われないことは明らかです。しかし、これは私たちが得ることができる「最善の努力の結果」でしょうか?

force_utf8(...)サブのヒューリスティック/機能をどのように改善しますか?

4

5 に答える 5

2

少しのドメイン知識を使用して修正できる場合があります。たとえば、√ は ISO-8859-1 ではありそうな文字の組み合わせではありません。UTF-8 é である可能性がはるかに高くなります。

入力が制限された文字プールに制限されている場合は、入力ストリームで Ã が発生しないと仮定するなどのヒューリスティックを使用することもできます。

この種のドメイン知識がなければ、問題は一般的に扱いにくいものになります。

于 2010-03-31T18:10:37.283 に答える
2

最初にEncode::Guessを使用してみることを除いて、提供できる有益なアドバイスはありません。

于 2010-03-31T22:19:05.823 に答える
1

この記事を見てください。UTF-8 は、西洋言語の文字を 8 ビットで表すように最適化されていますが、1 文字あたり 8 ビットに限定されません。マルチバイト文字は、共通のビット パターンを使用して、マルチバイトかどうか、およびその文字が使用するバイト数を示します。文字列内の 2 つのエンコーディングのみを安全に想定できる場合、残りは単純なはずです。

于 2010-03-31T18:16:17.383 に答える
1

文字を見ただけでは、それが ISO-8859-1 でエンコードされているか、UTF-8 でエンコードされているかを判断するのは困難です。問題は、どちらも 8 ビットのエンコーディングであるため、単純に MSb を見るだけでは不十分です。次に、すべての行について、UTF-8 であると仮定して行をトランスコードします。無効な UTF-8 エンコーディングが見つかった場合、その行が実際には ISO-8859-1 であると想定して、その行を再トランスコードします。このヒューリスティックの問題は、整形式の UTF-8 行でもある ISO-8859-1 行をトランスコードする可能性があることです。ただし、外部情報がなけれ$junkば、どちらが適切かを判断する方法はありません。

于 2010-03-31T17:55:33.633 に答える
0

つまり、「file -bi」と「iconv -f ISO-8859-1 -t UTF-8」で問題を解決することにしました。

最近、ファイル名のエンコーディングを正規化しようとして、同様の問題に遭遇しました。ISO-8859-1、UTF-8、および ASCII が混在していました。ファイルの処理中に気付いたので、ファイルのエンコーディングとは異なるエンコーディングを持つディレクトリ名が原因で複雑さが追加されました。

最初に Perl を使用しようとしましたが、UTF-8 と ISO-8859-1 を正しく区別できず、文字化けした UTF-8 が発生しました。

私の場合、妥当なファイル数での 1 回限りの変換だったので、知っていてエラーなしで動作する遅い方法を選択しました (ほとんどの場合、行ごとに 1 ~ 2 個の隣接していない文字のみが特別な ISO を使用していたためです)。 8859-1 コード)

オプション #1 は ISO-8859-1 を UTF-8 に変換します

猫の混合テキスト.txt |
読んでいる間
type=${"$(echo "$i" | file -bi -)"#*=}
[[ $type == 'iso-8859-1' ]]; それから
    エコー "$i" | iconv -f ISO-8859-1 -t UTF-8
そうしないと
    エコー "$i"
フィ
完了 > utf8_text.txt

オプション #2 は、ISO-8859-1 を ASCII に変換します

猫の混合テキスト.txt |
読んでいる間
type=${"$(echo "$i" | file -bi -)"#*=}
[[ $type == 'iso-8859-1' ]]; それから
    エコー "$i" | iconv -f ISO-8859-1 -t ASCII//TRANSLIT
そうしないと
    エコー "$i"
フィ
完了 > utf8_text.txt
于 2010-12-18T02:55:46.550 に答える