我在Perl中找到了LZW压缩/解压缩示例,我想让它适用于从文件压缩/解压缩。
以下是原始代码:
#Compress a string to a list of output symbols.
sub compress {
my $uncompressed = shift;
# Build the dictionary.
my $dict_size = 256;
my %dictionary = map {chr $_ => chr $_} 0..$dict_size-1;
my $w = "";
my @result;
foreach my $c (split '', $uncompressed) {
my $wc = $w . $c;
if (exists $dictionary{$wc}) {
$w = $wc;
} else {
push @result, $dictionary{$w};
# Add wc to the dictionary.
$dictionary{$wc} = $dict_size;
$dict_size++;
$w = $c;
}
}
# Output the code for w.
if ($w) {
push @result, $dictionary{$w};
}
return @result;
}
#Decompress a list of output ks to a string.
sub decompress {
my @compressed = @_;
# Build the dictionary.
my $dict_size = 256;
my %dictionary = map {chr $_ => chr $_} 0..$dict_size-1;
my $w = shift @compressed;
my $result = $w;
foreach my $k (@compressed) {
my $entry;
if (exists $dictionary{$k}) {
$entry = $dictionary{$k};
} elsif ($k == $dict_size) {
$entry = $w . substr($w,0,1);
} else {
die "Bad compressed k: $k";
}
$result .= $entry;
# Add w+entry[0] to the dictionary.
$dictionary{$dict_size} = $w . substr($entry,0,1);
$dict_size++;
$w = $entry;
}
return $result;
}
# How to use:
my @compressed = compress('TOBEORNOTTOBEORTOBEORNOT');
print "@compressed\n";
my $decompressed = decompress(@compressed);
print "$decompressed\n";
输出:
T O B E O R N O T 256 258 260 265 259 261 263 TOBEORNOTTOBEORTOBEORNOT
这是我的代码:
use strict;
use POSIX;
use Data::Dumper;
print "0 - compress; 1 - decompress:";
my $CD=<STDIN>;
$CD+=0;
if ($CD != 0 && $CD != 1) {print "Wrong symbol"."\n"}
if($CD==0){
print "Type the name of file you want to compress:";
my $file=<STDIN>;
open (DATAIN, "<$file") or die "There is no such a file $file: $!";
binmode (DATAIN);
my $uncompressed = <DATAIN>;
print "\n";
print "File to binary:\n";
print "$uncompressed\n";
# Build the dictionary.
my $dict_size = 256;
my %dictionary = map {chr $_ => chr $_} 0..$dict_size-1;
my $w = "";
my @result;
foreach my $c (split '', $uncompressed) {
my $wc = $w . $c;
if (exists $dictionary{$wc}) {
$w = $wc;
} else {
push @result, $dictionary{$w};
# Add wc to the dictionary.
$dictionary{$wc} = $dict_size;
$dict_size++;
$w = $c;
}
}
# Output the code for w.
if ($w) {
push @result, $dictionary{$w};
}
#print into screen
print "\n";
print "Compressed:\n";
print "@result\n";
#print into file
my $output = "output.txt";
open FILE, '>'.$output;
print FILE "@result";
close FILE;
}
if($CD==1){
print "Type the name of file you want to decompress:";
my $outfile=<STDIN>;
open (DATAIN, "<$outfile") or die "There is no such a file $outfile: $!";
binmode (DATAIN);
my @compressed = <DATAIN>;
# Build the dictionary.
my $dict_size = 256;
my %dictionary = map {chr $_ => chr $_} 0..$dict_size-1;
my $w = shift @compressed;
my $result = $w;
foreach my $k (@compressed) {
my $entry;
if (exists $dictionary{$k}) {
$entry = $dictionary{$k};
} elsif ($k == $dict_size) {
$entry = $w . substr($w,0,1);
} else {
die "Bad compressed k: $k";
}
$result .= $entry;
# Add w+entry[0] to the dictionary.
$dictionary{$dict_size} = $w . substr($entry,0,1);
$dict_size++;
$w = $entry;
}
print "$result\n";
}
所以,它压缩file.txt - “TOBEORNOTTOBEORTOBEORNOT”很好,但是当我想要解压缩输出文件 - output.txt - “TOBEORNOT 256 258 260 265 259 261 263”它失败了,只是给了我相同的“TOBEORNOT 256 258 260 265 259 261 263“结果。也许你有任何想法我的代码可能有什么问题?
答案 0 :(得分:0)
您正在将整个文件读入此行中@compressed
数组的第一个元素:
my @compressed = <DATAIN>;
但是你的print语句将它全部输出到一行。这意味着在my $w = shift @compressed
语句中,整个文本被移动到$w
变量中,因此下面的循环永远不会运行。
您需要按空格分割您读入的数据,如下所示:
my $compressed = <DATAIN>; # Data file contains only one line so read into scalar variable
my @compressed = split(/ /, $compressed);