设置菱形运算符在binmode中工作?

时间:2015-08-21 01:19:52

标签: perl

Diamond操作符(<>)默认以文本模式工作,是否可以更改binmode?似乎binmode函数只接受句柄。

2 个答案:

答案 0 :(得分:1)

请参阅perldoc perlopentut

  

二进制文件      在某些遗留系统上,可以称之为终端      复杂的(有些人会说破坏)I / O模型,文件不是文件 - 在      至少,不是与C标准I / O库有关。对这些旧的      其库(但不是内核)区分文本和文本的系统      二进制流,要使文件正常运行,你必须弯腰      向后避免讨厌的问题。在这种不恰当的系统上,插座      和管道已经以二进制模式打开,目前没有办法      把它关掉使用文件,您有更多选择。

     

另一种选择是在适当的句柄上使用“binmode”功能      在对它们进行常规I / O之前:

   binmode(STDIN);
   binmode(STDOUT);
   while (<STDIN>) { print }
     

传递“sysopen”非标准标志选项也将打开该文件      支持它的那些系统上的二进制模式。这相当于      正常打开文件,然后在句柄上调用“binmode”。

   sysopen(BINDAT, "records.data", O_RDWR | O_BINARY)
       || die "can't open records.data: $!";
     

现在您可以在该手柄上使用“read”和“print”而无需担心      非标准系统I / O库会破坏您的数据。这不是一个漂亮的      图片,但是,传统系统很少。 CP / M将与我们在一起直到      几天结束,之后。

     

在具有异国情调I / O系统的系统上,结果令人惊讶      足够的,甚至使用“sysread”和“syswrite”的无缓冲I / O可能会偷偷摸摸      背后的数据残割。

   while (sysread(WHENCE, $buf, 1024)) {
       syswrite(WHITHER, $buf, length($buf));
   }
     

根据运行时系统的变化,即使是这些调用也可能     首先需要“binmode”或“O_BINARY”。已知的系统没有这种系统     困难包括Unix,Mac OS,Plan 9和Inferno。

答案 1 :(得分:1)

<>是一种便利。如果它只通过命令行中指定的文件名进行迭代,则可以使用$ARGV中的while (<>)来检测新文件的打开时间,binmode,然后fseek一开始。当然,这在重定向的情况下不起作用(控制台输入是另一个故事)。

一种解决方案是检测@ARGV是否包含某些内容,并打开每个文件,默认为从STDIN读取。使用迭代器进行的基本实现可能是:

#!/usr/bin/env perl

use strict;
use warnings;
use Carp qw( croak );

my $argv = sub {
    @_ or return sub {
        my $done;
        sub {
            $done and return;
            $done = 1;
            binmode STDIN;
            \*STDIN;
        }
    }->();

    my @argv = @_;
    sub {
        @argv or return;
        my $file = shift @argv;
        open my $fh, '<', $file
            or croak "Cannot open '$file': $!";
        binmode $fh;
        $fh;
    };
}->(@ARGV);

binmode STDOUT;
while (my $fh = $argv->()) {
    while (my $line = <$fh>) {
        print $line;
    }
}

注意:

C:\...\Temp> xxd test.txt
00000000: 7468 6973 2069 7320 6120 7465 7374 0a0a  this is a test..

没有binmode

C:\...\Temp> perl -e "print " test.txt | xxd
00000000: 7468 6973 2069 7320 6120 7465 7374 0d0a  this is a test..
00000010: 0d0a                                     ..

使用上面的脚本:

C:\...\Temp> perl argv.pl test.txt | xxd
00000000: 7468 6973 2069 7320 6120 7465 7374 0a0a  this is a test..

使用perl ... < test.txt | xxd的相同结果,或perl ...

中的管道文字