2016-08-05 10 views
1

ruby​​ 2.2.1でrubyzip-1.2.0を使用して、単一のファイル(この場合はpythonスクリプト)を含むzipファイルを生成しています。コンテンツファイルは変更されず、生成されたzip文字列のmd5sumは変わりませんが、zip文字列を書き込んでからファイルに読み込むと、長さが増え、毎回md5sumが異なります。これは、File.open(zip_file, 'wb') {}またはIO.binwrite(zip_file, zip_string)のいずれを使用しても発生します。ruby​​zipの出力文字列と書かれたファイルのmd5sumは異なります

OS Xでは、zip文字列と書かれたファイルサイズが異なっています(もちろん、md5sumは異なります)。しかし、Ubuntu 14.04では、サイズは一貫しており、md5sumは異なります。

ファイルを複数回生成する場合、チェックサムは(一般的に)同じです。もし私が眠っていたら、それらは異なっているので、rubyzipがある種のタイムスタンプをファイルに書き込んでいるのだろうか?

私はおそらく、ルビバイナリファイル処理のニュアンスを見逃しています。 OS X上

require 'zip' 
require 'digest' 

def update_zip_file(source_file) 
    zip_file = source_file.sub(/py$/, 'zip') 
    new_zip = create_lambda_zip_file(source_file) 
    puts "Zip string length: #{new_zip.length}" 
    md5_string = Digest::MD5.new 
    md5_string.update IO.binread(zip_file) 
    puts "Zip string MD5: #{md5_string.hexdigest}" 
    File.open(zip_file, 'wb') do |f| 
    puts "Updating #{zip_file}" 
    f.write new_zip 
    end 
    puts "New file size: #{File.size(zip_file)}" 
    md5_file_new = Digest::MD5.new 
    md5_file_new.update IO.binread(zip_file) 
    puts "New file MD5: #{md5_file_new.hexdigest}" 
end 

def create_lambda_zip_file(source_file) 
    zip_file = source_file.sub(/py$/, 'zip') 
    zip = Zip::OutputStream.write_buffer do |zio| 
    zio.put_next_entry(File.basename(source_file)) 
    zio << File.read(source_file) 
    end 
    zip.string 
end 

(1..3).each do 
    update_zip_file('test.py') 
    sleep 2 
end 

出力:Ubuntuの14.04で

Zip string length: 973 
Zip string MD5: 2578d03cecf9539b046fb6993a87c6fd 
Updating test.zip 
New file size: 1019 
New file MD5: 03e0aa2d345cac9731d1482d2674fc1e 
Zip string length: 973 
Zip string MD5: 03e0aa2d345cac9731d1482d2674fc1e 
Updating test.zip 
New file size: 1019 
New file MD5: bb6fca23d13f1e2dfa01f93ba1e2cd16 
Zip string length: 973 
Zip string MD5: bb6fca23d13f1e2dfa01f93ba1e2cd16 
Updating test.zip 
New file size: 1019 
New file MD5: 3d27653fa1662375de9aa4b6d2a49358 

出力:

Zip string length: 1020 
Zip string MD5: 4a6f5c33b420360fed44c83f079202ce 
Updating test.zip 
New file size: 1020 
New file MD5: 0cd8a123fe7f73be0175b02f38615572 
Zip string length: 1020 
Zip string MD5: 0cd8a123fe7f73be0175b02f38615572 
Updating test.zip 
New file size: 1020 
New file MD5: 0a010e0ae0d75e5cde0c4c4ae098d436 
Zip string length: 1020 
Zip string MD5: 0a010e0ae0d75e5cde0c4c4ae098d436 
Updating test.zip 
New file size: 1020 
New file MD5: e91ca00a43ccf505039a9d70604e184c 

任意の説明や回避策?ファイルを書き換える前に、zipファイルの内容が異なることを確認したい。

ファイルmd5sumを修正し、出力を更新するように編集されました。

編集 実際、rubyzipは現在のタイムスタンプを各エントリに入れています(なぜ?)。私が猿のパッチを当ててエントリ属性を操作できるようにすると、zip文字列のmd5sumは一定のままです。

module Zip 
    class OutputStream 
    attr_accessor :entry_set 
    end 

    class Entry 
    attr_accessor :time 
    end 
end 

... 

def create_lambda_zip_file(source_file) 
    zip_file = source_file.sub(/py$/, 'zip') 
    zip = Zip::OutputStream.write_buffer do |zio| 
    zio.put_next_entry(File.basename(source_file)) 
    zio << File.read(source_file) 
    zio.entry_set.each {|e| puts e.time = Zip::DOSTime.at(File.mtime(source_file).to_i)} 
    end 
    zip.string 
end 
+0

は、ファイルの変更のエンコーディングをい助けるかもしれないASCII-8BITにエンコーディングを変更するforce_encodingを使用しているのですか?例えば、ISO8859からUTF-8へ。 – spickermann

答えて

0

8caba7d65b81501f3b65eca199c28acetest.zipのMD5チェックサムです:あなたは、ファイル名をmd5'dました。

長さの差はおそらくString#lengthが文字列のコードポイントの数を返しているのに対して、File.sizeはバイトを数えているためです。 String#bytesizeメソッドは、ファイルチェックと同じものを返す必要があります。

私のマシン(OS X、ruby 2.3.1)では、zipから返された文字列は、長さがバイト数と同じではない理由を説明するエンコードutf-8を持つと主張しています。文字列は実際には有効なUTF8ではありませんが、これはバグだと思います。どちらの異なるバージョンまたはおそらくロケール関連の環境変数は、郵便番号データを装っていないLinuxマシンをもたらしているがUTF8

+0

投稿するコードを凝縮していたときに、内容ではなくファイル名のmd5sumが発生しました。元の投稿を編集します。また、私が見たオリジナルの問題は隠されていました。これは長さの変更だけでなく、ファイル内容チェックサム上の移動ターゲットでした。 zipファイルの適切なエンコーディングは何ですか? –

+0

ASCII-8BIT(またはその同義語バイナリ) –

関連する問題