2016-09-28 55 views
6

提交我有一個方法荏苒:寫zip文件Clojure中

(defn zip-project [project-id notebooks files] 
    (with-open [out (ByteArrayOutputStream.) 
       zip (ZipOutputStream. out)] 
    (doseq [nb notebooks] 
     (.putNextEntry zip (ZipEntry. (str "Notebooks/" (:notebook/name nb) ".bkr"))) 
     (let [nb-json (:notebook/contents nb) 
      bytes (.getBytes nb-json)] 
     (.write zip bytes)) 
     (.closeEntry zip)) 
    (doseq [{:keys [name content]} files] 
     (.putNextEntry zip (ZipEntry. (str "Files/" name))) 
     (io/copy content zip) 
     (.closeEntry zip)) 
    (.finish zip) 
    (.toByteArray out))) 

後我做一個拉鍊我想把它保存到文件類似/tmp/sample/sample.zip,但我似乎無法做到。這裏是我在做什麼:

(defn create-file! [path zip] 
    (let [f (io/file path)] 
    (io/make-parents f) 
    (io/copy zip f) 
    true)) 

的問題是,當我從終端運行unzip它說,zip文件是空的,如果我解壓縮使用存檔工具是它cpgz擴展提取。

我在這裏做錯了什麼?

+0

我的直覺是,問題是,你調用'(.toByteArray出)(。toByteArray out)''with-open'內部,所以一些字節可能仍然在ZipOutpu中被刷新T流。所以你寧願重構'(.toByteArray(with-open [...] out))''。 – cgrand

+0

當我運行'(創建文件!「/tmp/sample/sample.zip」(zip-project 1 [{:notebook/name「Hello」:notebook/contents「yadada」}] [{:name「name」 :content「content」}]))創建文件'/ tmp/sample/sample.zip'。當我解壓縮時,我看到一個文件夾「Notebooks」,文件「Hello.bkr」和「yadada」作爲內容。所以對於這些虛擬值,它可以在我的機器上正常工作。你傳遞給'zip-project'的是什麼'notebooks'和'files'?你可以將它們添加到問題中嗎? –

回答

1

你基本上需要4個東西

  1. 進口一切(通常你會使用(ns ...),但你可以在REPL

    (import 'java.io.FileOutputStream) 
    (import 'java.io.BufferedOutputStream) 
    (import 'java.io.ZipOutputStream) 
    (import 'java.util.zip.ZipOutputStream) 
    (import 'java.util.zip.ZipEntry) 
    
  2. 您需要一種方法來初始化流運行此。這可以用->宏很好地完成:

    (defn zip-stream 
        "Opens a ZipOutputStream over the given file (as a string)" 
        [file] 
        (-> (FileOutputStream. file) 
         BufferedOutputStream. 
         ZipOutputStream.)) 
    
  3. 您需要一種方式來創建在ZipOutputStream

    (defn create-zip-entry 
        "Create a zip entry with the given name. That will be the name of the file inside the zipped file." 
        [stream entry-name] 
        (.putNextEntry stream (ZipEntry. entry-name))) 
    
  4. /關閉條目最後,你需要一種方式來寫你的內容。

    (defn write-to-zip 
        "Writes a string to a zip stream as created by zip-stream" 
        [stream str] 
        (.write stream (.getBytes str))) 
    
  5. 全部放在一起:

    (with-open [stream (zip-stream "coolio.zip")] 
        (create-zip-entry stream "foo1.txt") 
        (write-to-zip stream "Hello Foo1") 
        (.closeEntry stream) ;; don't forget to close entries 
        (create-zip-entry stream "foo2.txt") 
        (write-to-zip stream "Hello Foo 2") 
        (.closeEntry stream)) 
    
  6. 結果:

The result

+0

我似乎無法得到格式正確,將不勝感激,如果有人可以給我一隻手:) – fernandohur