我在文件中打开了一个文件句柄,其中包含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来删除写入磁盘的需要,但我仍然需要将整个内容读入内存.似乎有一种方法可以使用管道来传输它,但我现在还没想办法做到这一点.
您可以编写自己的转换模块PerlIO
并将其与:via(MODULE)
. 您的模块可以传递数据以Text::Iconv
从一种字符集转换为另一种字符集。
这种方式在手册中有描述PerlIO::via(3pm)
。简而言之,您需要创建自己的模块,例如PerlIO::via::Example
\xe2\x80\x94,即创建PerlIO/via
目录并放在Example.pm
那里,其中包含以下内容:
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
像这里一样使用它:
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