【问题标题】:Why is my filehandler empty?? PERL为什么我的文件处理程序是空的? PERL
【发布时间】:2016-04-27 20:50:05
【问题描述】:

我对 Perl 完全陌生,我有一段代码返回了一个空文件处理程序。

my $md5dir = "...plib/test/md5sum";    #IN MY PROG, IS THE FULL PATH
opendir( DIR, $md5dir ) or die "Can't open directory $md5dir: $!";
my @md5files = grep !/^\.\.?$/, readdir(DIR);
closedir(DIR);

if (  scalar @md5files < 1
   || scalar @md5files > 8
   || ( scalar @md5files % 2 != 0 ) )
{
   print "Incorrect amount of files in directory. Aborting.\n";
   exit 1;
}
else {
   for ( my $i = 0; ( $i < scalar @md5files / 2 ); $i++ ) {
      my $file1 = $md5files[$i];
      open( my $fh1, $file1 ) or die "Fail to open file $file1 $!";
      my $file2 = $md5files[ $i + 3 ];
      open( my $fh2, $file2 ) or die "Fail to open file $file2 $!";
      print "2.", $file1, " ", $file2, "\n";
      my $first1 = substr( $file1, 0, 4 );
      my $first2 = substr( $file2, 0, 4 );
      if ( ( $first1 cmp $first2 ) == 0 ) {
         if   ( eof $fh1 ) { print "No lines\n"; }
         else              { my $line1 = <$fh1>; print "$line1\n"; }
         if   ( eof $fh2 ) { print "No lines2\n"; }
         else              { my $line2 = <$fh2>; print "$line2\n"; }
         close $fh1;
         close $fh2;
      }
   }    # for
}    # else

输出是这样的:

2.SAM5_27-04-2016_11:21:20.md5 SAM5_27-04-2016_11:20:11.md5
No lines
No lines2
2.SAM6_27-04-2016_11:18:25.md5 SAM6_25-04-2016_10:38:38.md5
No lines
No lines2
2.SAM4_27-04-2016_11:19:06.md5 SAM4_27-04-2016_11:17:22.md5
No lines
No lines2

在 md5sum 的目录中:

:md5sum>ls -la
total 16
drwxrwxr-x   2 ateam    ateam       4096 Apr 27 11:24 ./
drwxrwxr-x   4 ateam    ateam       4096 Apr 27 11:24 ../
-rw-rw-r--   1 ateam    ateam         63 Apr 27 11:17 SAM4_27-04-2016_11:17:22.md5
-rw-rw-r--   1 ateam    ateam         63 Apr 27 11:19 SAM4_27-04 2016_11:19:06.md5
-rw-rw-r--   1 ateam    ateam         63 Apr 27 11:20 SAM5_27-04-2016_11:20:11.md5
-rw-rw-r--   1 ateam    ateam          0 Apr 27 11:21 SAM5_27-04-2016_11:21:20.md5
-rw-rw-r--   1 ateam    ateam         63 Apr 25 10:38 SAM6_25-04-2016_10:38:38.md5
-rw-rw-r--   1 ateam    ateam         63 Apr 27 11:18 SAM6_27-04-2016_11:18:25.md5

有人可以解释为什么文件处理程序是空的吗?我验证了文件的打印。它们都可以很好地打印到数组中,并且文件处理程序正在打开...由于文件不为空,还有什么问题??? (好吧,除了那个……)

只是为了查看文件...以防万一。 打开我得到的第一个文件:

03c0cf2ab0da62832bfc6970d4505746  SAM4_27-04-2016_11:17:22.csv

编辑::: 我对文件稍作调整:

if (($first1 cmp $first2) == 0) {
            if (tell($fh1) == -1){ print "No lines\n";}
            else {my $line1= <$fh1>;  print "$line1\n"; }
            if (eof $fh2){ print "No lines2\n";}
            else { my $line2= <$fh2>; print "$line2\n"; }
            close $fh1;                     close $fh2;
}

而是得到了这个输出:

2.SAM5_27-04-2016_11:21:20.md5 SAM5_27-04-2016_11:20:11.md5
Use of uninitialized value in concatenation (.) or string at mulftptest line 53.

No lines2
2.SAM6_27-04-2016_11:18:25.md5 SAM6_25-04-2016_10:38:38.md5
Use of uninitialized value in concatenation (.) or string at mulftptest line 53.

No lines2
2.SAM4_27-04-2016_11:19:06.md5 SAM4_27-04-2016_11:17:22.md5
Use of uninitialized value in concatenation (.) or string at mulftptest line 53.

No lines2

基本上,我知道这告诉我我正在尝试使用“空”变量。但是,我不明白为什么它是空的。

【问题讨论】:

  • @eballes 它默认为'
  • '<:encoding>
  • 我试过了,没用。
  • 您确定文件已打开?如果文件关闭,eof 返回 0。
  • @HunterMcMillen:错了。 OP 表示根据文件的前四个字符对文件进行配对。 readdir 返回的值可能按其名称的词法顺序传递,因此它们应该以$md5files[$i]$md5files[$i+1] 访问,同时循环将$i 增加2。您的建议期望每对的第二个文件向后排序,例如SAM4_1SAM5_1SAM6_1SAM6_2SAM5_2SAM4_2;而 OP 的代码适用于 SAM4_1SAM5_1SAM6_1SAM4_2SAM5_2SAM6_2

标签: perl null file-handling


【解决方案1】:

主要问题是readdir只返回文件名,没有任何路径信息

这意味着您在当前工作目录中打开SAM5_27-04-2016_11:21:20.md5,而不是在md5sum 目录中。通常你的打开调用会失败,但你的脚本目录中似乎有同名的虚假空文件

如果你这样写你的公开电话,那么它应该适合你

open my $fh1, '<', "$md5dir/$file1" or die "Fail to open file $file1: $!";

不要将tell 用于此目的。无论文件是否为空,它都会在开始时返回零。你真的想要-s $fh1,它以字节为单位返回文件的大小,并且可以用于文件名或打开的文件句柄

【讨论】:

  • 只有在这种情况下才会在开始时告诉 return 0 ?我认为 tell 对于这种目的很有用。
  • 有些东西告诉我这是对的。让我在今天早上验证它,然后我会接受这个答案。谢谢。
  • @noc_coder: tell 返回到目前为止从文件中读取的字节数。在您打开文件后立即读取零字节,因此tell 将返回零,无论是否还有其他内容要读取
  • 就是这样!非常感谢您的帮助!
【解决方案2】:

我最好的猜测是你需要这样的东西。我很确定您有一个包含 MD5 校验和的文件目录并想要比较它们

我通过这些方式使这更简单

  • 我在程序顶部有use autodie。这是一个检查大多数 Perl IO 操作的编译指示,并且可以帮助您验证每个 open 调用是否成功。它被引入到 v5.10.1 的核心 perl 中并且是可靠的

  • 我添加了use constant作为MD5文件目录的路径

  • 我使用glob 而不是opendir / readdir 来查找md5sum 目录中以.md5 结尾的所有文件。 glob 永远不会返回伪目录...,但如果有人很奇怪,xx.md5 总是有可能是一个目录。您可能需要添加支票

有一个循环来构建一个哈希,该哈希将每个“前缀”(前缀是文件名中第一个下划线之前的所有字符)与具有该前缀的每个文件相关联

检查该哈希以确保目录中的每个前缀都有确切的文件。这似乎与原始支票一致

现在有一个哈希将每个前缀与两个文件相关联,问题似乎已经解决了。我的代码显示每个前缀及其两个文件的名称和它们包含的 MD5 字符串

use strict;
use warnings 'all';
use autodie;

use constant MD5_DIR => '...plib/test/md5sum';    #IN YOUR PROG, IS THE FULL PATH
chdir MD5_DIR;

my %files;

# Build a hash of files collected by prefix
#
for my $file ( glob '*.md5' ) {
    next unless my ($prefix) = $file =~ / ^ ( [^_]+ ) /x;
    push @{ $files{$prefix} }, $file;
}


# Check that there are exactly two files with each prefix
#
{
    my $errors;

    while ( my ($prefix, $files) = each %files ) {

        my $n = @$files;

        if ( @$files != 2 ) {
            warn qq{$n files fouhd for prefix "${prefix}_"\n};
            ++$errors;
        }
    }

    die "Dying because errors found in source directory" if $errors;
}

# Display every pair of files by prefix
#
while ( my ($prefix, $files) = each %files ) {

    my ($file1, $file2) = sort @$files;

    print "Prefix: $prefix\n";

    for my $file ( sort @$files ) {
        open my $fh, '<', $file;
        my $md5 = <$fh>;
        $md5 =~ s/\s+\z//;
        print "    File: $file\n";
        print "        MD5: $md5\n";
    }
}

【讨论】:

    猜你喜欢
    • 2015-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-17
    • 1970-01-01
    • 2011-06-25
    • 2021-08-16
    相关资源
    最近更新 更多