Perl:我如何获得";字节读取";来自md5::digest addfile()?

Perl:我如何获得";字节读取";来自md5::digest addfile()?,perl,md5,Perl,Md5,我使用Digest::MD5计算数据流的MD5;也就是说,一个gzip文件(或者准确地说,3000)太大,无法放入RAM中。所以我要这样做: use Digest::MD5 qw(md5_base64); my ($filename) = @_; # this is in a sub my $ctx = Digest::MD5 -> new; $openme = $filename; # Usually, it's a plain f

我使用Digest::MD5计算数据流的MD5;也就是说,一个gzip文件(或者准确地说,3000)太大,无法放入RAM中。所以我要这样做:

 use Digest::MD5 qw(md5_base64);

 my ($filename) = @_;                # this is in a sub
 my $ctx = Digest::MD5 -> new;

 $openme = $filename;        # Usually, it's a plain file
 $openme = "gunzip -c '$filename' |" if ($filename =~ /\.gz$/); # is gz

 open (FILE, $openme); # gunzip to STDOUT
 binmode(FILE);
 $ctx -> addfile(*FILE);   # passing filehandle
 close(FILE);
这是一个成功
addfile
在gunzip的输出中整齐地发出咕噜声,并给出正确的MD5

但是,我非常非常想知道slurped数据的大小(在本例中为gunzipped“file”)

我可以再加一句

  $size = 0 + `gunzip -c very/big-file.gz | wc -c`;
但这需要读取两次文件

是否有任何方法可以从Digest::MD5提取slurped的字节数?我尝试捕获结果:
$result=$ctx->addfile(*FILE)和在$result和$ctx上执行Data::Dumper,但没有出现任何有趣的结果


编辑:文件通常不是gzip文件。添加代码以显示我的实际工作。

您可以自己阅读内容,并将其输入到
$ctx->add($data)
中,并记录您传递的数据量。无论是在单个调用中添加所有数据,还是跨多个调用添加所有数据,都不会对底层算法产生任何影响。这些文件包括:


这表明您可以一次只做一件。

您可以自己阅读内容,并将其输入到
$ctx->add($data)
,并记录您传递的数据量。无论是在单个调用中添加所有数据,还是跨多个调用添加所有数据,都不会对底层算法产生任何影响。这些文件包括:


这表明您可以一次只做一个片段。

我会用perl来完成这一切,而不依赖外部程序进行解压缩:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use IO::Uncompress::Gunzip qw/$GunzipError/;
use Digest::MD5;

my $filename = shift or die "Missing gzip filename!\n";

my $md5 = Digest::MD5->new;
# Allow for reading both gzip format files and uncompressed files.
# This is the default behavior, but might as well be explicit about it.
my $z = IO::Uncompress::Gunzip->new($filename, Transparent => 1)
  or die "Unable to open $filename: $GunzipError\n";
my $len = 0;

while ((my $blen = $z->read(my $block)) > 0) {
  $len += $blen;
  $md5->add($block);
}
die "There was an error reading the file: $GunzipError\n" unless $z->eof;

say "Total uncompressed length: $len";
say "MD5: ", $md5->hexdigest;

如果您想使用
gunzip
而不是核心
IO::Uncompress::gunzip
模块,您可以执行类似的操作,不过可以使用
read
一次获取一块数据:

#!/usr/bin/perl
use warnings;
use strict;
use autodie; # So we don't have to explicitly check for i/o related errors
use feature qw/say/;
use Digest::MD5;

my $filename = shift or die "Missing gzip filename!\n";

my $md5 = Digest::MD5->new;
# Note use of lexical file handle and safer version of opening a pipe
# from a process that eliminates shell shenanigans. Also uses the :raw
# perlio layer instead of calling binmode on the handle (which has the
# same effect)
open my $z, "-|:raw", "gunzip", "-c", $filename;
# Non-compressed version
# open my $z, "<:raw", $filename;
my $len = 0;

while ((my $blen = read($z, my $block, 4096)) > 0) {
  $len += $blen;
  $md5->add($block);
}

say "Total uncompressed length: $len";
say "MD5: ", $md5->hexdigest;
#/usr/bin/perl
使用警告;
严格使用;
使用autodie;#因此,我们不必显式地检查与i/o相关的错误
使用功能qw/say/;
使用Digest::MD5;
my$filename=shift或die“缺少gzip文件名!\n”;
my$md5=摘要::md5->新建;
#注意词汇文件句柄的使用和打开管道的更安全版本
#从一个消除壳牌骗局的过程中。也使用:生的
#perlio层,而不是在句柄上调用binmode(该句柄具有
#(效果相同)
打开我的$z,“-|:原始”、“gunzip”、“-c”、$filename;
#非压缩版本

#打开我的$z,“我会用perl来完成这一切,而不依赖外部程序进行解压缩:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use IO::Uncompress::Gunzip qw/$GunzipError/;
use Digest::MD5;

my $filename = shift or die "Missing gzip filename!\n";

my $md5 = Digest::MD5->new;
# Allow for reading both gzip format files and uncompressed files.
# This is the default behavior, but might as well be explicit about it.
my $z = IO::Uncompress::Gunzip->new($filename, Transparent => 1)
  or die "Unable to open $filename: $GunzipError\n";
my $len = 0;

while ((my $blen = $z->read(my $block)) > 0) {
  $len += $blen;
  $md5->add($block);
}
die "There was an error reading the file: $GunzipError\n" unless $z->eof;

say "Total uncompressed length: $len";
say "MD5: ", $md5->hexdigest;

如果您想使用
gunzip
而不是核心
IO::Uncompress::gunzip
模块,您可以执行类似的操作,不过可以使用
read
一次获取一块数据:

#!/usr/bin/perl
use warnings;
use strict;
use autodie; # So we don't have to explicitly check for i/o related errors
use feature qw/say/;
use Digest::MD5;

my $filename = shift or die "Missing gzip filename!\n";

my $md5 = Digest::MD5->new;
# Note use of lexical file handle and safer version of opening a pipe
# from a process that eliminates shell shenanigans. Also uses the :raw
# perlio layer instead of calling binmode on the handle (which has the
# same effect)
open my $z, "-|:raw", "gunzip", "-c", $filename;
# Non-compressed version
# open my $z, "<:raw", $filename;
my $len = 0;

while ((my $blen = read($z, my $block, 4096)) > 0) {
  $len += $blen;
  $md5->add($block);
}

say "Total uncompressed length: $len";
say "MD5: ", $md5->hexdigest;
!/usr/bin/perl
使用警告;
严格使用;
使用autodie;#这样我们就不必显式地检查与i/o相关的错误
使用功能qw/say/;
使用Digest::MD5;
my$filename=shift或die“缺少gzip文件名\n”;
my$md5=摘要::md5->新建;
#注意词汇文件句柄的使用和打开管道的更安全版本
#从一个消除贝壳骗局的过程中。也使用:生的
#perlio层,而不是在句柄上调用binmode(该句柄具有
#(效果相同)
打开我的$z,“-|:原始”、“gunzip”、“-c”、$filename;
#非压缩版本

#打开我的$z,“可能用于一次读取一个块的文件,并在运行时计算数据长度及其摘要,而不是依赖外部程序?可能用于一次读取一个块的文件,并在运行时计算数据长度及其摘要,而不是依赖外部程序?有趣。我的问题的一部分是我不能依赖gzip的文件。现在,代码是用来读取普通文件的,我有一个简单的垫片:`if/gz$/{$filename=“gunzip-c$filename |“}在打开之前卡住了。@Harper模块的默认行为是,如果文件不是gzip格式,只需原封不动地传递它即可(这可以通过构造函数的
Transparent
选项显式设置;让我更新代码以显示这一点。)@Shawn,这真是太好了。嗯,等等。这个模块对一个本来应该是gzip文件,但有文件损坏的文件做了什么?我有一些这样的文件。@Harper还添加了一些错误报告,用于在解压缩文件时遇到问题。有趣的是。我的部分问题是我不能依赖gzip文件。现在,这个代码是用来读取普通文件的,我有一个简单的垫片:`if/gz$/{$filename=“gunzip-c$filename |”}卡在打开之前。@Harper模块的默认行为是,如果文件不是gzip格式,只需原封不动地传递它(这可以通过构造函数的
Transparent
选项显式设置;让我更新代码以显示这一点。)@Shawn,这真是太好了。嗯,等等。模块对一个本应是gzip文件但有文件损坏的文件做了什么?我有一些这样的文件。@Harper还添加了一些错误报告,用于在解压缩文件时遇到问题。