web-dev-qa-db-ja.com

Rubyでディスクに保存せずにZipファイルを生成するにはどうすればよいですか?

メモリ内に多数のPDFファイルを生成しましたが、電子メールの添付ファイルとして送信する前に1つのZipファイルに圧縮したいと思います。Rubyzipを確認しましたが、Zipを作成できません。ディスクに保存せずにファイルします(多分私は間違っています)。

一時ファイルを作成せずにそれらのファイルを圧縮する方法はありますか?

37
Martinos

Rubyzipgemとstringioオブジェクトを使用して解決した同様の問題がありました。 rubyzipは、stringioオブジェクトを返すメソッドZipOutputStream.write_bufferを提供していることがわかりました。

put_next_entryを使用してZipファイル構造を自由に作成して書き込むことができます。終了したら、stringioを巻き戻して、sysreadを使用してバイナリデータを読み取ることができます。

次の簡単な例を参照してください(rubyzip 0.9.Xで動作します)

require 'Zip/zip'
stringio = Zip::OutputStream.write_buffer do |zio|
  zio.put_next_entry("test.txt")
  zio.write "Hello world!"
end
stringio.rewind
binary_data = stringio.sysread

Jruby 1.6.5.1(Ruby-1.9.2-p136)(2011-12-27 1bf37c2)(Java HotSpot(TM)64ビットサーバーVM 1.6.0_29)[Windows Server 2008-AMD64-Java])

次の例は、rubyzip> = 1.0.0で機能します

require 'rubygems'    
require 'Zip'
stringio = Zip::OutputStream.write_buffer do |zio|
  zio.put_next_entry("test.txt")
  zio.write "Hello world!"
end
binary_data = stringio.string

OpenJDK64ビットサーバー上のjruby1.7.22(1.9.3p551)2015-08-20c28f492でテスト済みVM 1.7.0_79-b14 + jit [linux-AMD64]およびrubyzipgem1.1。 7

53
vas

Rubyには非常に便利なStringIOライブラリが付属しています。これは、文字列を出力IOオブジェクトとして使用したり、文字列に基づくファイルの読み取りを偽造したりするために使用できます。

ここでの課題は、RubyZipがZip::ZipOutputStreamの作成時にIOオブジェクトを直接取得することをサポートしていないことですが、initializeの実装を見ると、意欲によって異なります。実験するために、クラスを拡張して、コンストラクターでIOオブジェクトまたはファイル名のいずれかを取ることができる場合があります。

5
rud

私が見つけた2つのRubyZipライブラリがあります。

  1. ChilkatのRuby Zipライブラリ
  2. Sourceforgeのrubyzip

Chilkatのライブラリでは、次のリンクに示されているように、Zipファイルをディスクに自動的に書き込むのではなく、メモリ内に作成できます。 Zip to MemoryZip from in memory data

一方、SourceForgeのものは、ファイルをメモリに圧縮するオプションを提供する場合がありますが、私はRubyに非常に慣れていないため、完全にはわかりません。 SourceForgeのrubyzipはJava.util.Zipに基づいているため、 ZipOutputStream というクラスがあります。 rubyzipの実装がどれほど優れているかはわかりませんが、Java.util.Zipの実装では、 OutputStreamByteArrayOutputStreamFileOutputStreamFilterOutputStreamObjectOutputStreamOutputStreamPipedOutputStreamに設定できます。

それがrubyzipの実装に当てはまる場合は、ZipOutputStreamを使用して、メモリに出力されるような種類のByteArrayOutputStreamを渡す必要があります。

それがrubyzipに存在しない場合は、いつでも独自の実装を作成して、オープンソースであるためrubyzipに含めるために送信できると確信しています。

1
mezoid

Linuxを使用している場合、RAMの量とファイルの大きさに応じて、常にtmpfs(共有メモリ)を使用できます。次に、rubyzipディスクベースの方法動作します。 http://www.mjmwired.net/kernel/Documentation/filesystems/tmpfs.txt

0
g33kz0r