圧縮ファイルをさらに圧縮してみた記録

2011 年 1 月 31 日 by 山平

圧縮したいファイルを何度も圧縮したら、どんどん小さくなっちゃうんじゃないの!?
誰もがそう思ったことがあるのではないでしょうか?そうでもないですか?
難しいアルゴリズムは置いておいて、実際のところどうなのかを試してみました。

まずは単純に5回zip圧縮してみます。
圧縮に使ったファイルは以前と同様にデジカメ動画(写真)フリー素材様からお借りしています。

compress.rb(同じファイルを5回zip圧縮する)

#!/usr/bin/ruby

source='asianele.wmv'
5.times do
destin="#{source}.zip"
`zip #{destin} #{source}`
source=destin
end

実行結果

$ ruby compress.rb
$ ls -l | grep asianele.wmv
合計 2812
-rw-r–r– 1 ymh ymh 547350 2011-01-30 16:50 asianele.wmv
-rw-r–r– 1 ymh ymh 459316 2011-01-30 17:02 asianele.wmv.zip
-rw-r–r– 1 ymh ymh 459498 2011-01-30 17:02 asianele.wmv.zip.zip
-rw-r–r– 1 ymh ymh 459688 2011-01-30 17:02 asianele.wmv.zip.zip.zip
-rw-r–r– 1 ymh ymh 459886 2011-01-30 17:02 asianele.wmv.zip.zip.zip.zip
-rw-r–r– 1 ymh ymh 460092 2011-01-30 17:02 asianele.wmv.zip.zip.zip.zip.zip

なんとzipをzipすると、ジワジワとファイルサイズが増えていきます。
なんだか悔しいので、バイナリを可逆な範囲で散らしてみます。

binshuffle.rb(ファイルをシャッフルする)

#!/usr/bin/ruby

source, destin = *ARGV
raise ArgumentError, 'invalid path 1.' if !source or !destin
raise ArgumentError, 'invalid path 2.' if !File.exist?(source)
raise ArgumentError, 'invalid path 3.' if File.exist?(destin)

stack = []
ios = File.open(source, 'r+b')
iod = File.open(destin, 'w+b')
ios.each_byte {|ch|
stack.unshift((255 ^ ch))
if stack.length >= 1024 then
iod.write(stack.pack('c*'))
stack = []
end
}
iod.write(stack.pack('c*')) if stack.length > 0
iod.close
ios.close

shcomp.rb(同じファイルを5回zip圧縮+シャッフルする)

#!/usr/bin/ruby

source='asianele.wmv'
5.times do
destinz="#{source}.zip"
destins="#{destinz}.shf"
`zip #{destinz} #{source}`
`ruby binshuffle.rb #{destinz} #{destins}`
source=destins
end

実行結果

$ ruby shcomp.rb
asianele.wmv -> asianele.wmv.zip -> asianele.wmv.zip.shf
asianele.wmv.zip.shf -> asianele.wmv.zip.shf.zip -> asianele.wmv.zip.shf.zip.shf
asianele.wmv.zip.shf.zip.shf -> asianele.wmv.zip.shf.zip.shf.zip -> asianele.wmv.zip.shf.zip.shf.zip.shf
asianele.wmv.zip.shf.zip.shf.zip.shf -> asianele.wmv.zip.shf.zip.shf.zip.shf.zip -> asianele.wmv.zip.shf.zip.shf.zip.shf.zip.shf
asianele.wmv.zip.shf.zip.shf.zip.shf.zip.shf -> asianele.wmv.zip.shf.zip.shf.zip.shf.zip.shf.zip -> asianele.wmv.zip.shf.zip.shf.zip.shf.zip.shf.zip.shf
$ ls -l | grep asianele.wmv
-rw-r–r– 1 ymh ymh 547350 2011-01-30 16:50 asianele.wmv
-rw-r–r– 1 ymh ymh 459316 2011-01-30 22:41 asianele.wmv.zip
-rw-r–r– 1 ymh ymh 459316 2011-01-30 22:41 asianele.wmv.zip.shf
-rw-r–r– 1 ymh ymh 459581 2011-01-30 22:41 asianele.wmv.zip.shf.zip
-rw-r–r– 1 ymh ymh 459581 2011-01-30 22:41 asianele.wmv.zip.shf.zip.shf
-rw-r–r– 1 ymh ymh 459862 2011-01-30 22:41 asianele.wmv.zip.shf.zip.shf.zip
-rw-r–r– 1 ymh ymh 459862 2011-01-30 22:41 asianele.wmv.zip.shf.zip.shf.zip.shf
-rw-r–r– 1 ymh ymh 460159 2011-01-30 22:41 asianele.wmv.zip.shf.zip.shf.zip.shf.zip
-rw-r–r– 1 ymh ymh 460159 2011-01-30 22:41 asianele.wmv.zip.shf.zip.shf.zip.shf.zip.shf
-rw-r–r– 1 ymh ymh 460461 2011-01-30 22:41 asianele.wmv.zip.shf.zip.shf.zip.shf.zip.shf.zip
-rw-r–r– 1 ymh ymh 460461 2011-01-30 22:41 asianele.wmv.zip.shf.zip.shf.zip.shf.zip.shf.zip.shf

なんとさっきよりもやや大きい幅でジワジワとファイルサイズが増えていきます。
簡単には行かないようです。
悔しい。。

華々しい結果にはなりませんでしたが、今回は以上です。

タグ:

TrackBack