【问题标题】:Perl file upload. How to access filehandle multiple times?Perl 文件上传。如何多次访问文件句柄?
【发布时间】:2013-05-06 19:30:39
【问题描述】:

我正在尝试检测上传的文件是否为有效的 UTF-8,然后才对其内容进行一些操作。它可以检测到非 UTF-8 文件,但如果文件是有效的 UTF-8,则没有要处理的内容。 while(){} 循环中没有要处理的数据。我的错误在哪里?

use utf8;
use CGI qw(:all -utf8);
use Encode;

my $q           = new CGI;

my $file        = $q->param('importfile');
my $file_handle = $q->upload('importfile');
my $fhtest      = do {
        local $/;
        <$file_handle>;
};

my $utf8;
eval { $utf8 = decode( "utf8", $fhtest, Encode::FB_CROAK ) };
if ($@) {
        die 'Not a valid UTF-8 file';
}

binmode $file_handle, ':encoding(UTF-8)';
while (<$file_handle>) {
        chomp();
        # my code here
}

【问题讨论】:

    标签: perl upload filehandle


    【解决方案1】:

    当您使用readline(又名&lt;$fh&gt;)时,您会在上次中断的地方阅读下一行。您在文件末尾离开了。

    当然,您也许可以使用seek 来回退文件句柄(假设它不是管道),但是为什么要再次从文件中读取呢?您已经将整个内容保存在内存中,并且也已经解码!把它分成几行。

     my $file_contents; { local $/; $file_contents = <$file_handle>; }
    
    utf8::decode($file_contents)
       or die 'Not a valid UTF-8 file';
    
    for (split /^/m, $file_contents, -1) {
        chomp;
        ...
    }
    

    或者因为你无论如何都在咀嚼,

    for (split /\n/, $file_contents) {
        ...
    }
    

    我避免使用do,因为它会导致在内存中创建文件的额外副本。

    【讨论】:

      【解决方案2】:

      当您创建$fhtest 时,您已经在第一个循环中读取了整个文件句柄。如果想回到开头,可以使用seek

      use Fcntl ':seek';    # import constants
      ...
      my $fhtest      = do {
              local $/;
              <$file_handle>;
      };
      
      my $utf8;
      eval { $utf8 = decode( "utf8", $fhtest, Encode::FB_CROAK | Encode::LEAVE_SRC) };
      if ($@) {
              die 'Not a valid UTF-8 file';
      }
      
      seek $file_handle, 0, SEEK_SET;
      
      # now you can start over with $file_handle
      

      当然,由于您已经将所有数据加载到内存中的$fhtest 中,您可以只在换行符(或其他)上split 并循环遍历结果。或者你可以打开一个假的文件句柄来处理你已经在内存中的东西:

      open my $fake_fh, '<', \$fhtest;
      while( <$fake_fh> ) { 
          ....
      }
      

      【讨论】:

      • 谢谢!第一种带有seek 的方法可以正常工作。尝试第二个打开假文件句柄 - 在while 循环中没有要处理的数据。这就是策略,$fhtest 确实包含数据,但不知何故它没有传递给假文件句柄。
      • 使用Encode::FB_CROAK | Encode::LEAVE_SRC 解决了这个问题。固定。
      猜你喜欢
      • 2015-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-13
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多