我试图找出许多输入字符串的编码,一些是UTF-8,一些是ISO-8859-1。不幸的。
我正在使用Perl和Encode::Guess
,我很惊讶它看到它无法处理简单的Latin1编码。我正在使用Encode :: Guess文档中的解码示例。
我一直在阅读文件,但我也可以对字符串进行硬编码以获得相同的错误:
use Encode::Guess;
my $data = "The name \xc5sa is Swedish\n";
my $enc = guess_encoding($data,qw/latin1 utf8 ascii/);
ref($enc) or die "Can't guess: $enc\nFOR: $data";
我得到了:
Can't guess: No appropriate encodings found!
FOR: The name �sa is Swedish
虽然在我的编辑中,我看到“Åsa”与Aring作为第一个角色。
Perl是否预先确定了编码,因为它是一个字符串,而不是一组打包的二进制数据,那是什么打破了这个?
当我从文件中读取时,我尝试了use open ":encoding(Latin1)";
,错误消失了,但它猜测编码为UTF-8。无论如何,该文件在逐行的基础上混合使用UTF-8和Latin1,因此我想为每一行运行Encode::Guess
。
我还在文件句柄上尝试了binmode
,但仍然看到错误。
答案 0 :(得分:4)
这一行
my $enc = guess_encoding($data,/latin1 utf8 ascii/);
应该是
my $enc = guess_encoding($data,qw/latin1 utf8 ascii/);
^^
答案 1 :(得分:2)
您的程序有问题。参数/latin1 utf8 ascii/
正在尝试将正则表达式模式应用于(未定义的)变量$_
。你会看到一条警告信息
在模式匹配(m //)
中使用未初始化的值$ _
你真的应该告诉我们
请注意,use open ":encoding(Latin1)"
与在打开文件句柄时将binmode $fh, ":encoding(Latin1)"
应用于每个文件句柄相同,并会在您阅读时尝试将数据解码为Latin1。结果将是一个字符串,它使用Perl的内部编码来处理文件中的Latin1字符。如果其中一些是UTF-8那么那将是灾难性的。 A-ring字符的UTF-8编码是两个字节C3
85
,被视为Latin1,是A-tilde,后跟非法字符
这应该对你有用
use strict;
use warnings 'all';
use feature 'say';
use Encode::Guess;
for my $data (
"The name \xC5sa is Swedish\n",
"The name \N{U+00C5}sa is Swedish\n" ) {
my $enc = guess_encoding($data, qw/ latin1 utf8 ascii /);
ref($enc) or die "Can't guess: $enc\nFOR: $data";
say $enc->name;
}
iso-8859-1
utf8
我强烈推荐Grant McLean的Encoding::FixLatin
模块,它可以满足您的所有需求。它还将涵盖两种编码在一行中使用的情况
此程序使用Latin1
处理编码的字符串,使用UTF-8
处理另一个字符串。使用fix_latin
use strict;
use warnings 'all';
use feature 'say';
use open qw/ :std :encoding(UTF-8) /;
use Encoding::FixLatin 'fix_latin';
for my $data (
"The name \xC5sa is Swedish\n",
"And so is Asbj\N{U+00F6}rn\n" ) {
my $utf8 = fix_latin($data);
print $utf8;
}
The name Åsa is Swedish
And so is Asbjörn
最好使用这种技术一次读取和处理整个文件。除非文件很大并且会导致内存问题,否则逐行读取文件是没有意义的