我在一个包含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
这似乎是一堆额外的工作。有没有办法直接流式传输?我知道我可以使用IO::Scalar来消除对磁盘写入的需要,但我仍然需要将整个内容读取到内存中。似乎有一种方法可以通过管道进行流式传输,但我现在还没有想办法做到这一点。
您可以为PerlIO
编写自己的转换模块,并将其与:via(MODULE)
一起使用。您的模块可以通过Text::Iconv
传递数据,以便从一个字符集转换到另一个字符集中。
PerlIO::via(3pm)
手册中介绍了这种方式。简而言之,您需要创建自己的模块,例如PerlIO::via::Example
——也就是说,您制作PerlIO/via
目录并将Example.pm
放在那里,内容如下:
package PerlIO::via::Example;
use strict;
use warnings;
use Text::Iconv;
my $converter = Text::Iconv->new("windows-1252", "utf-8");
sub PUSHED
{
my ($class, $mode, $fh) = @_;
# When writing we buffer the data
my $buf = '';
return bless $buf, $class;
}
sub FILL
{
my ($obj, $fh) = @_;
my $line = <$fh>;
return (defined $line) ? 'converted: ' . $converter->convert($line) : undef;
# 'converted: ' is added here for debugging purposes
}
sub WRITE
{
my ($obj,$buf,$fh) = @_;
$$obj .= $buf; # we do nothing here
return length($buf);
}
sub FLUSH
{
my ($obj, $fh) = @_;
print $fh $$obj or return -1;
$$obj = '';
return 0;
}
1;
然后在open
中使用,如下所示:
use strict;
use warnings;
use PerlIO::via::Example;
open(my $fh, "<:via(Example)", "input.txt");
while (<$fh>) {
print;
}
close $fh;
您可以使用外部程序来转换输入文件。详见perldoc -f open
。
open( my $ft, '-|' "iconf -f CP1252 -t UTF-8 1252.txt") || die $!;
附言:perl库有更简单的解决方案。以上是最一般的IMHO。