我有以下打开文本文件的子项,并尝试确保其编码为UTF-8,ISO-8859-15或ASCII之一。
我遇到的问题是交互式和非交互式使用中的行为不同。
当我与包含UTF-8行的文件进行交互运行时,按预期,$decoder
是一个引用对象,其name
返回该行的utf8。
非交互(因为它作为Subversion提交钩子的一部分运行)guess_encoding
返回utf8 or iso-8859-15
检查行的标量字符串utf8
和{{ 1}}用于其他两行。
我不能一辈子,找出行为差异来自何处。如果我强制将iso-8859-15 or utf8
的编码说成open
,它将毫无疑问地接受每一行作为UTF-8。
问题是我不能假设它接收到的每个文件都是UTF-8,所以我不想强制编码作为变通方法。另一个可能的解决方法是解析标量文本,但这似乎很混乱,尤其是当它在交互式上下文中似乎可以正常工作时。
我已经尝试从外壳程序中覆盖<:encoding(utf8)
(由于未设置为非交互方式,因此$LANG
变量均未设置),但是交互版本仍然可以正常运行。 / p>
注释为LC_
的注释行在注释时以交互和非交互方式返回0。
最终,我们要防止的一件事是在存储库中使用UTF-16或其他宽字符编码(因为我们的某些工具不能很好地使用它):我以为寻找白色-编码列表比查找黑名单要容易得多。
$Encode::Guess::NoUTFAutoGuess
答案 0 :(得分:1)
无需猜测。对于UTF-8,ISO-8859-1和US-ASCII的特定选项,可以使用Encoding::FixLatin的fix_latin
。是virtually guaranteed to succeed。
也就是说,我认为OP中使用ISO-8859-1是ISO-8859-15的错字。
fix_latin
使用的方法在ISO-8859-15中和在ISO-8859-1中一样有效。这只是将_init_byte_map
替换为以下内容的问题:
sub _init_byte_map {
foreach my $i (0x80..0xFF) {
my $byte = chr($i);
my $utf8 = Encode::from_to($byte, 'iso-8859-15', 'UTF-8');
$byte_map->{$byte} = $utf8;
}
}
或者,如果您愿意假设数据全部是一种编码或另一种编码(而不是混合编码),则还可以使用以下方法:
my $text;
if (!eval {
$text = decode("UTF-8", $bytes, Encode::FB_CROAK|Encode::LEAVE_SRC);
1 # No exception
}) {
$text = decode("ISO-8859-15", $bytes);
}
请记住,US-ASCII是UTF-8和ISO-8859-15的适当子集,因此不需要特殊处理。