如何在事先不知道所使用的编码的情况下将文本编码为 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"; }
}

这不是一个通用工具,但它可能有助于作为实现您自己的启发式方法的起点。

相关内容