2014-10-03 28 views
6

我有一个文件句柄在其中包含cp1252字符的文件上打开。我想把这个打开的文件句柄放到一个需要原始utf8字节的库中,它将通过网络发送这些文件。Perl将文件句柄就地/从cp1252流式传输到utf-8?

天真的方式做到这一点是写文件拿出来与正确的编码第二个文件,并给第二个文件句柄到库:

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去除写入磁盘的需要,但是我仍然必须将整个内容读入内存。似乎有一种方法可以用流水线进行流式处理,但我现在没有想办法做到这一点。

+0

你说的是Perl库或非perl的库/ propgram?你能给你的操作系统命名(unix/windows)吗? – AnFi 2014-10-03 18:26:43

+1

注意:'open ...,“1252.txt”|| die!!;'表示开放......,(“1252.txt”|| die $!);'(它永远不会死亡)。你想要'打开...,“1252.txt”或者死掉$ !;' – ikegami 2014-10-03 19:44:20

回答

3

您可以编写自己的转换模块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; 
+0

这看起来好像会起作用,但工作在这个问题上的工程师回应道:“如果我们正在处理一个文件,他的答案会奏效在本地文件系统上(在他的例子中,'input.txt'),但是我们只是从mogilefs获得一个已经打开的文件句柄,所以我们不能通过他概述的新的PerlIO模块。“非常棒的答案,谢谢! – 2014-11-07 17:31:06

0

您可以使用外部程序来转换输入文件。详情请参阅perldoc -f open

open(my $ft, '-|' "iconf -f CP1252 -t UTF-8 1252.txt") || die $!; 

P.S. perl库有更简单的解决方案。以上是最通用的恕我直言。