perl - 读取文件时自动检测字符编码

标签 perl io character-encoding

<分区>

我有时不得不从外部来源读取文本文件,这些文件可以使用各种字符编码;通常是 UTF-8、Latin-1 或 Windows CP-1252。

有没有办法方便地读取这些文件,像 Vim 等编辑器一样自动检测编码?

我希望得到像这样简单的东西:

open(my $f, '<:encoding(autodetect)', 'foo.txt') or die 'Oops: $!';

请注意 Encode::Guess不能解决问题:它仅在可以明确检测到编码时才有效,否则它会发出声音。大多数 UTF-8 数据名义上是有效的 latin-1 数据,因此它在 UTF-8 文件上失败。

例子:

#!/usr/bin/env perl

use 5.020;
use warnings;

use Encode;
use Encode::Guess qw(utf-8 cp1252);

binmode STDOUT => 'utf8';

my $utf8 = "H\x{C3}\x{A9}llo, W\x{C3}\x{B8}rld!"; # "Héllo, Wørld!" in UTF-8
my $latin = "H\x{E9}llo, W\x{F8}rld!";            # "Héllo, Wørld!" in CP-1252

# Version 1
my $enc1 = Encode::Guess->guess($latin);
if (ref($enc1)) {
    say $enc1->name, ': ', $enc1->decode($latin);
}
else {
    say "Oops: $enc1";
}
my $enc2 = Encode::Guess->guess($utf8);
if (ref($enc2)) {
    say $enc2->name, ': ', $enc2->decode($utf8);
}
else {
    say "Oops: $enc2";
}

# Version 2
say decode("Guess", $latin);
say decode("Guess", $utf8);

输出:

cp1252: Héllo, Wørld!
Oops: utf-8-strict or utf8 or cp1252
Héllo, Wørld!
cp1252 or utf-8-strict or utf8 at ./guesstest line 32.

Borodin 的回答中“更新”下的版本仅适用于 UTF-8 数据,但适用于 Latin-1 数据。 如果您需要同时处理 UTF-8 和 Latin-1 文件,则不能使用 Encode::Guess

这不是与 this one 相同的问题: 我正在寻找一种在打开文件时自动检测的方法。

最佳答案

这是我目前的解决方法。至少对于 UTF-8 和 Latin-1(或 Windows-1252)文件来说是这样。

use 5.024;
use experimental 'signatures';
use Encode qw(decode);

sub slurp($file)
{
    # Read the raw bytes
    local $/;
    open (my $fh, '<:raw', $file) or return undef();
    my $raw = <$fh>;
    close($fh);

    my $content;

    # Try to interpret the content as UTF-8
    eval { my $text = decode('utf-8', $raw, Encode::FB_CROAK); $content = $text };

    # If this failed, interpret as windows-1252 (a superset of iso-8859-1 and ascii)
    if (!$content) {
        eval { my $text = decode('windows-1252', $raw, Encode::FB_CROAK); $content = $text };
    }

    # If this failed, give up and use the raw bytes
    if (!$content) {
        $content = $raw;
    }

    return $content;
}

关于perl - 读取文件时自动检测字符编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51208958/

相关文章:

windows - 字符编码,UTF 还是 ANSI?

java - 如何使用 jTDS 为 Sybase JDBC 连接指定字符集?

perl - 按字典顺序排序

perl - perl 模块可以 "use"其他 perl 模块吗?

java - 使用 XSSFWorkbook 附加到现有的 excel 文件

java - Apache 公共(public) I/O。如何通过通配符过滤文件?

java - 如何在 Java 中查找默认字符集/编码?

perl - 如何使用 Perl 合并重叠元素?

perl - 为什么我的 Perl CGI 会提示 "Premature end of script headers"?

go - 长时间运行复制到 bytes.Buffer