【问题标题】:Unicode in Perl not workingPerl 中的 Unicode 不起作用
【发布时间】:2010-07-22 00:05:54
【问题描述】:

我有一些文本文件,我试图在 Windows 上使用 Perl 脚本对其进行转换。文本文件在 Notepad+ 中看起来很正常,但我脚本中的所有正则表达式都无法匹配。然后我注意到,当我在 NotePad+ 中打开文本文件时,状态栏显示“UCS-2 Little Endia”(原文如此)。我假设这对应于编码 UCS-2LE。所以我在 Perl 中创建了“readFile”和“writeFile”子程序,如下所示:

use PerlIO::encoding;

my $enc = ':encoding(UCS-2LE)';

sub readFile {
    my ($fName) = @_;
    open my $f, "<$enc", $fName or die "can't read $fName\n";
    local $/;
    my $txt = <$f>;
    close $f;
    return $txt;
}

sub writeFile {
    my ($fName, $txt) = @_;
    open my $f, ">$enc", $fName or die "can't write $fName\n";
    print $f $txt;
    close $f;
}

my $fName = 'someFile.txt';

my $txt = readFile $fName;
# ... transform $txt using s/// ...
writeFile $fName, $txt;

现在正则表达式匹配(虽然比我预期的要少),但输出包含长字符串,其中穿插着正确文本的长字符串。我的代码错了吗?或者 Notepad+ 的编码可能是错误的?我应该如何进行?

【问题讨论】:

  • 提供一些测试数据,额外的 hexdump 是个好主意。显示导致问题的完整代码。如果您不能让我们重现问题,我们只能推测。
  • @daxim:这里的代码相当完整,我无法检查的唯一原因是因为我没有notepad+编辑器可以比较。猜测是 BOM 问题。

标签: perl unicode


【解决方案1】:

好的,我想通了。问题是由“open”调用的“encoding...”参数完成的编码转换与 Perl 在 Windows 上完成的默认 CRLF 转换之间的脱节引起的。似乎正在发生的事情是 LF 在输出 编码已经完成之后被转换为 CRLF,这为下一行抛出了 16 位编码的“奇偶校验”。一旦到达下一行,“平价”就被放回去了。这可以解释“一长串看起来像亚洲人的字符,中间穿插着长串的正确文本”……每隔一行都被弄乱了。

为了更正它,我在我的“open”调用中取出了编码参数并添加了一个“binmode”调用,如下所示:

open my $f, $fName or die "can't read $fName\n";
binmode $f, ':raw:encoding(UCS-2LE)';

binmode 显然有一个“分层”I/O 处理的概念,这有点复杂。

我想不通的一件事是如何恢复我的 CRLF 翻译。如果我省略 :raw 或添加 :crlf,“奇偶校验”问题就会返回。我也尝试过重新订购,但无法正常工作。

(我将此作为单独的问题添加:CRLF translation with Unicode in Perl

【讨论】:

    【解决方案2】:

    我没有要检查的 Notepad+ 编辑器,但这可能是您的输出编码不包含 BOM 的 BOM 问题。

    http://perldoc.perl.org/Encode/Unicode.html#Size%2c-Endianness%2c-and-BOM

    也许您需要如上所述使用字节顺序标记对 $txt 进行编码。

    【讨论】:

      猜你喜欢
      • 2015-11-30
      • 2016-01-06
      • 2018-09-07
      • 1970-01-01
      • 1970-01-01
      • 2015-11-05
      • 1970-01-01
      • 2014-07-22
      • 2013-04-13
      相关资源
      最近更新 更多