2010-03-09 26 views
32

我已經在內存中生成了很多PDF文件,我想在將它們作爲電子郵件附件發送之前將它們壓縮到一個zip文件中。我看了Rubyzip,它不允許我創建一個zip文件而不保存到磁盤(也許我錯了)。如何在不使用Ruby保存到磁盤的情況下生成zip文件?

有什麼辦法可以壓縮這些文件而不創建臨時文件?

+0

請參閱[@vas的答案] (http://stackoverflow.com/a/9712252/244128),它正是你想要的! – maerics 2012-05-21 15:09:00

回答

38

我有一個類似的問題,我使用rubyzip gem和stringio對象解決了這個問題。 事實證明,rubyzip提供了一種返回字符串對象的方法:ZipOutputStream.write_buffer

您可以使用put_next_entry來創建zip文件結構,只要您使用put_next_entry並寫入,一旦完成,您可以倒回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(紅寶石-1.9.2-P136)(2011-12-27 1bf37c2)(Java的熱點(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 

在JRuby測試1.7.22(1.9.3p551)2015年8月20日c28f492 OpenJDK的64- Bit Server VM 1.7.0_79-b14 + jit [linux-amd64]和rubyzip gem 1.1.7

+0

謝謝,它的工作原理。然而,在我寫這個問題的時候,這個方法還沒有存在。它在2011-01-07添加。感謝您的回答,下次我需要在記憶中壓縮,我會知道如何。 – Martinos 2012-09-06 21:35:41

+1

LoadError無法加載這樣的文件 - zip – 2014-01-28 13:48:04

+1

上面的作品使用舊版本的rubyzip gem。版本1.0改變了界面。請看:https://github.com/rubyzip/rubyzip#important-note – vas 2014-01-31 01:16:06

1

我能找到兩個RubyZip庫。

  1. Chilkat's Ruby Zip Library
  2. rubyzip on Sourceforge

奇爾卡特的庫中明確允許使用一個自動在內存中創建一個zip文件,而不是將其寫入磁盤的在這些鏈接看到:Zip to MemoryZip from in memory data

的另一方面,SourceForge可能會提供一個壓縮文件的選項,但我並不完全確定,因爲我對ruby很陌生。 SourceForge ruby​​zip基於java.util.zip,導致它擁有一個名爲ZipOutputStream的類。我不知道有多好,rubyzip實現,但java.util.zip實施OutputStream可以設置爲ByteArrayOutputStreamFileOutputStreamFilterOutputStreamObjectOutputStreamOutputStreamPipedOutputStream ....

如果爲rubyzip實施成立則它應該是使用ZipOutputStream來傳遞ByteArrayOutputStream種類的問題,這會導致它被輸出到內存。

如果它不存在於rubyzip中,那麼我相信你總是可以編寫自己的實現並提交它包含在rubyzip中,因爲它是開源的。

+0

我指的是寶石:http://rubygems.org/gems/rubyzip 我不想使用奇爾卡特庫,因爲它不是開源的。 – Martinos 2010-03-09 01:06:26

+0

我不會降低這一點,但我沒有在任何地方發現類似「不,標準Ruby ZIP類不能做到這一點」的評論。我相信你應該開始使用它。 – dimitarvp 2010-03-10 11:59:40

+0

事實上,ZipOutputStream新方法以文件名作爲參數,我沒有找到任何方式來傳遞IO對象。 – Martinos 2010-03-10 20:06:40

0

如果你在Linux上,並且根據你有多少RAM以及你的文件有多大,你總是可以使用tmpfs(共享內存)。然後,rubyzip基於磁盤的方法將會起作用。 http://www.mjmwired.net/kernel/Documentation/filesystems/tmpfs.txt

+0

掛載需要超級用戶權限 – 2011-09-23 18:55:23

+0

@AbeVoelker是的,這個答案假設你已經有一個tmpfs,或者有一個友好的本地系統管理員。 – g33kz0r 2011-09-25 19:09:27

5

Ruby帶有一個非常方便的StringIO庫 - 這可用於使用String作爲輸出IO對象或僞造讀取由String支持的文件。

這裏的挑戰是RubyZip在創建Zip::ZipOutputStream時不支持直接獲取IO對象,但如果您看一下initialize的實現,並根據您的實驗意願,可以擴展該類並允許它在構造函數中使用IO對象或文件名。

相關問題