使用されたエンコーディングを事前に知らずにテキストをUTF-8にエンコードする方法は?

使用されたエンコーディングを事前に知らずにテキストをUTF-8にエンコードする方法は?

テキストをUTF-8に変換する方法はいくつかありますが、すべて現在使用中のテキストエンコーディングを指定する必要があります。

以前にどのような用途に使用されたのか気にせずに複数のファイルをUTF-8に一括変換する方法はありますか?

答え1

これは難しい質問ですが、私はかなり頻繁に遭遇する質問です。私はさまざまなアプローチを使用して一連のスクリプトを作成しました。簡単なスクリプトを紹介します(ヨーロッパのラテン環境でutf8を保証)。

  • 各ファイルに対応するタイプと文字セットを要求します(file -i)。
  • 一般的な状況を処理し、バックアップを維持する方法を決定します。
  • 多くの場合…何もしないでください!
  • 場合によっては、デフォルト値を使用します(例ではCP1252 / latin1)
#!/usr/bin/perl
use strict;
my $charset;

for(@ARGV){
  $charset="?";
  next if /.bak$/;
  my $type = `file -b -i '$_'`;   ### use file -i for  charset and type
  if($type =~ /(\S+);\s+charset=(\S+)/){$type=$1; $charset=lc($2)};

  next    if($charset eq "utf-8") ;
  next    if($charset eq "binary") ;
  next    if($charset eq "us-ascii")  ;
  next    if($type eq "application/postscript");

  if($type eq "application/xml"){
    rename($_ ,"$_.bak");
    system ("xmllint --encode utf-8 '$_.bak' > '$_'\n")  }
  elsif($charset eq "non-iso" or $charset eq "unknown-8bit" ) {
    rename($_ ,"$_.bak");
    system ("iconv -f CP1252 -t utf-8 '$_.bak' > '$_'\n")  }  ## DANGER
  elsif($charset eq "utf-16le"){
    rename($_ ,"$_.bak");
    system ("iconv -f $charset  -t utf-8 '$_.bak' > '$_'\n")  }
  elsif($charset eq "iso-8859"  or  $charset eq "iso-8859-1"){
    rename($_ ,"$_.bak");
    system ("iconv -f latin1 -t utf-8 '$_.bak' > '$_'\n")  }
  else { print "HELP: '$type:$charset' '$_'\n"; }
}

これは一般的なツールではありませんが、独自の経験的な方法を実装するための出発点として役立ちます。

関連情報