Perl将文件句柄就地/流式传输从cp1252转换为utf-8?

Kev*_* G. 6 perl utf-8

我在文件中打开了一个文件句柄,其中包含cp1252个字符.我想将这个打开的文件句柄提供给一个期望原始utf8字节的库,它将通过网络发送它们.

这种天真的方法是将文件写入具有正确编码的第二个文件,并将第二个文件句柄提供给库:

use Fcntl qw/SEEK_SET/;

open my $fh_1252, "<:encoding(cp1252)", "1252.txt" || die $!;

open my $fh_utf8, "+>:encoding(utf8)", "utf8.txt"  || die $!;

while (<$fh_1252>){ print $fh_utf8 $_ };

seek($fh_utf8, 0, SEEK_SET);

# now give $fh_utf8 to the library for transmission
Run Code Online (Sandbox Code Playgroud)

这似乎是一堆额外的工作.有没有办法简单地流动它?我知道我可以使用IO :: Scalar来删除写入磁盘的需要,但我仍然需要将整个内容读入内存.似乎有一种方法可以使用管道来传输它,但我现在还没想办法做到这一点.

afe*_*ter 3

您可以编写自己的转换模块PerlIO并将其与:via(MODULE). 您的模块可以传递数据以Text::Iconv从一种字符集转换为另一种字符集。

\n\n

这种方式在手册中有描述PerlIO::via(3pm)。简而言之,您需要创建自己的模块,例如PerlIO::via::Example\xe2\x80\x94,即创建PerlIO/via目录并放在Example.pm那里,其中包含以下内容:

\n\n
package PerlIO::via::Example;\n\nuse strict;\nuse warnings;\n\nuse Text::Iconv;\nmy $converter = Text::Iconv->new("windows-1252", "utf-8");\n\nsub PUSHED\n{\n    my ($class, $mode, $fh) = @_;\n    # When writing we buffer the data\n    my $buf = \'\';\n    return bless \\$buf, $class;\n}\n\nsub FILL\n{\n    my ($obj, $fh) = @_;\n    my $line = <$fh>;\n    return (defined $line) ? \'converted: \' . $converter->convert($line) : undef;\n    # \'converted: \' is added here for debugging purposes\n}\n\nsub WRITE\n{\n    my ($obj,$buf,$fh) = @_;\n    $$obj .= $buf; # we do nothing here\n    return length($buf);\n}\n\nsub FLUSH\n{\n    my ($obj, $fh) = @_;\n    print $fh $$obj or return -1;\n    $$obj = \'\';\n    return 0;\n}\n\n1;\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后open像这里一样使用它:

\n\n
use strict;\nuse warnings;\n\nuse PerlIO::via::Example;\n\nopen(my $fh, "<:via(Example)", "input.txt");\nwhile (<$fh>) {\n    print;\n}\nclose $fh;\n
Run Code Online (Sandbox Code Playgroud)\n