无法使用 $|=1; 关闭 Perl 中的缓冲。

6
我正在写入两个文件,一个是使用Log_message函数记录日志,另一个是在file_write函数中写入OUT,我想逐行写入而不是缓冲,以便它按行而不是在脚本结束时一次性写入。
我已经了解了缓冲和热文件处理的相关知识,但无法让我的代码正常运行。在此示例中,我在foreach循环之前添加了$ | = 1;但它仍然一次写入。我做错了什么吗?
如果有必要,我已将整个脚本放在下面。
    #-----------------------------------------------
    sub file_write {
    #-----------------------------------------------
    open OUT, ">>$OUT" or Log_message ("\n$DATE - $TIME - ERROR - Could not create filelist.doc \t");
    Log_message ("\n$DATE - $TIME - INFO - Opened the output file");
    my $total = scalar keys %{ $doc->{ resource } };
    Log_message ("\n$DATE - $TIME - INFO - Found: " . $total . " resources");
    #printf "resources: %s\n", scalar keys %{ $doc->{ resource } }; 

   $|=1;

    #And I have also tried:

    #use IO::Handle;
    #STDOUT->autoflush(1);

    foreach ( keys %{ $doc->{ resource } } ) {
        #print OUT $doc->{ resource }->{ $_ }->{ id }, "\n";
        my $ID = $doc->{ resource }->{ $_ }->{ id }, "\n";
        Log_message ("\n$DATE - $TIME - INFO - Found: " . $ID);
        my $testurl = "http://dronlineservices.letterpart.com/web/content.xql?action=doc_html&lang=en&pub=" . $pubId . "&docid=" . $ID;
         print OUT "$testurl\n";
      sleep 1;

    }

整个脚本
#   !c:/Perl/bin/Perl.exe


#-----------------------------------------------
#Modules
#-----------------------------------------------
use XML::Simple;
use LWP;
use Data::Dumper;
$Data::Dumper::Indent = 1;
$Data::Dumper::Sortkeys = 1; 
use strict;
use warnings;

#-----------------------------------------------
#Declare variables
#-----------------------------------------------
    my $script = "LiveContent Auto Cache Script";   # Name of the script
    my $version = "Version 0.1";
    #my $pubId = "COMP-20110922XXXX";
    my $pubId = "LiveContentDoc";       
    my $OUT = "output.txt";
    my $LOG = "cacher-log.log";     # Location of log file
    my $DATE;                                                   # Date in form 2001-sep-01
  my $DATENR;                                               # Date in form 2001-01-09 
  my $TIME;                                             # Time in form 12:04:03
  my $txtmesg = "";
  my $resource;
  my $xs;
  my $doc;

####################################
########### Main Program ###########
####################################
error_logger();                             # Open Log file and time stamp it
request_url(); #Open the xml url and read it in
file_write();  #write the contents of the xml url to a file


#-----------------------------------------------
sub request_url {
#-----------------------------------------------
my $useragent = LWP::UserAgent->new;
my $request = HTTP::Request->new( GET => "http://digitalessence.net/resource.xml" );
#my $request = HTTP::Request->new( GET => "http://dronlineservices.letterpart.com/web/content.xql?action=index&lang=en&pub=" . $pubId );
$resource = $useragent->request( $request );  
$xs         = XML::Simple->new();
$doc        = $xs->XMLin( $resource->content );

}


#-----------------------------------------------
sub file_write {
#-----------------------------------------------
open OUT, ">>$OUT" or Log_message ("\n$DATE - $TIME - ERROR - Could not create filelist.doc \t");
Log_message ("\n$DATE - $TIME - INFO - Opened the output file");
my $total = scalar keys %{ $doc->{ resource } };
Log_message ("\n$DATE - $TIME - INFO - Found: " . $total . " resources");
#printf "resources: %s\n", scalar keys %{ $doc->{ resource } };



use IO::Handle;
STDOUT->autoflush(1);

foreach ( keys %{ $doc->{ resource } } ) {
    #print OUT $doc->{ resource }->{ $_ }->{ id }, "\n";
    my $ID = $doc->{ resource }->{ $_ }->{ id }, "\n";
    Log_message ("\n$DATE - $TIME - INFO - Found: " . $ID);


    my $testurl = "http://dronlineservices.letterpart.com/web/content.xql?action=doc_html&lang=en&pub=" . $pubId . "&docid=" . $ID;
     print OUT "$testurl\n";


        #   my $browser = LWP::UserAgent->new;
        #   $browser->timeout(240);
        #   $browser->env_proxy;
        #   $browser->agent('Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)');

            # my $response = $browser->get($testurl);

        #    if ($response->is_success) {
             #     print "\n############################\n";
             #     print "$testurl\n";
             #     print "\n############################\n";
              #   print $response->decoded_content;  # print the response out
            # }
            # else {
             #    my $error = $response->status_line;
            #     Log_message ("\n$DATE - $TIME - WARN - Can't load $ID because: $error");
             #    die $response->status_line;

        #   }



    #my $loadrequest = $ua->get('http://dronlineservices.letterpart.com/web/content.xql?action=doc_html&lang=en&pub=" . $pubId . "&docid=" . $ID');
    sleep 1;

}


Log_message ("\n$DATE - $TIME - INFO - Written the output file");
#close(OUT) or Log_message ("\n$DATE - $TIME - WARN - Failed to close the Output file");
Log_message ("\n$DATE - $TIME - INFO - Closed the output file");
}
#-----------------------------------------------
sub error_logger {
#-----------------------------------------------
    time_stamp();                                                                                                                               # Run Time stamp sub
    open LOG, ">>$LOG" or die ("could not open log file <$LOG>");                               # Open Log File
    Log_message ("\n$DATE - $TIME - -----------------------------------------\ \t");
        Log_message ("\n$DATE - $TIME - INFO - Start of Application\ \t");
        Log_message ("\n$DATE - $TIME - INFO - $script\ \t");
        Log_message ("\n$DATE - $TIME - INFO - $version\ \t");
        Log_message ("\n$DATE - $TIME - -----------------------------------------\ \t");

}
#-------------------------------------------------------------
sub Log_message {
#-------------------------------------------------------------
    time_stamp();                   # Run time_stamp every time the log is written to
    my($mesg) = @_;
    print LOG $mesg if $LOG;    # Print to log file
    print $mesg;              # Print to Screen
    $txtmesg = $mesg;
    #print "\nLOGGING: $txtmesg\n";
} 
#-----------------------------------------------
sub time_stamp {
#-----------------------------------------------
    my($Sec,$Min,$Hour,$Day,$MonthNr,$Year) = localtime(time());
    my $Month=("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec")[$MonthNr];
    $Sec = sprintf("%02d",$Sec);
    $Min = sprintf("%02d",$Min);
    $Day = sprintf("%02d",$Day);
    $MonthNr = sprintf("%02d",++$MonthNr);
    $Year = 1900 + $Year;
    $DATE = "$Year-$Month-$Day";
    $DATENR = "$Year-$MonthNr-$Day";
    $TIME = "$Hour:$Min:$Sec";
} # end sub
2个回答

19

你忘记先选择句柄了。

select( (select(OUT), $| = 1)[0] );

4
想要解释这行代码,可以参考文档 (perldoc perlvar):如果设为非零值,则在当前选定的输出通道上进行每次写入或打印操作后立即执行清空缓存的操作。请注意,“当前选定的”是关键。 - Marco De Lellis
非常感谢。现在我要阅读文档以更好地理解它! - Hedley Phillips

13
use IO::Handle;
OUT->autoflush(1);

但最好使用词法文件句柄:

use IO::Handle;
open my $outfh, ">>", $OUT or Log_message ("\n$DATE - $TIME - ERROR - Could not create filelist.doc \t");
$outfh->autoflush(1);

1
没有任何括号,这很难阅读。此外,问题是关于如何正确使用 $| 的。你的回答没有解决这个问题。最后,你说词法文件句柄,但你并不是这个意思。你的意思是自动创建的句柄。 - tchrist
3
@tchrist,当然可以。正确使用 $| 的方法是不通过 autoflush 使用它。 - ikegami
@ikegami,这种“正确”的感觉相当愚蠢。$|并没有被弃用,假装它已经被弃用对任何人都没有好处。 - tchrist
@tchrist,我没有说过弃用,我是说这个工具(除了标准输出)不适合这项工作。 - ikegami
糟糕!在之前的消息中,s/is to not use it via autoflush/is to use it via autoflush/。 - ikegami

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接