习惯性的Clojure将资源从运行的jar复制到外部

这似乎是一个古典问题,但我无法找到任何关于它的“clojure方式”。

所以,我在资源/(leiningen项目)中有一个foo /目录。 当jar'd / uberjar'd,这个foo /目录放在jar的根目录下。 由于jar内的文件在运行时可能并不一致,因此不能使用基本复制功能将目录递归复制到外部世界。

存在几种Java世界的解决方案(如何编写一个可以提取JAR文件并将其数据存储在指定目录(位置)的Java程序?以及如何从jar资源中提取目录(和子目录)?例如),但我没有找到任何现有的Clojure解决方案。 作为初学者(包括Clojure和Java),我不确定如何将以上解决方案转换为Clojure。 从字面上逐行翻译Java到Clojurish Java Interop似乎不太合适。 是否有一种“官方”,clojure-idiomatic的方式来做到这一点?

请注意,我正在使用Raynes的fs公用程序库。 似乎没有直接执行此操作的功能,但是可能有一些元素可用于简化此过程? (除了明显的基本碘糖)


几个月前我写了cpath-clj,它将通过URI列出类路径中的资源。 您可以尝试以下操作:

(require '[cpath-clj.core :as cp]
         '[clojure.java.io :as io])

(doseq [[path uris] (cp/resources (io/resource "foo"))
        :let [uri (first uris)
              relative-path (subs path 1)
              output-file (io/file output-directory relative-path)]]
  (with-open [in (io/input-stream uri)]
    (io/copy in output-file)))

由于图书馆没有考虑到这个用例,所以有一些杂耍正在进行:

  • (cp/resources (io/resource "foo"))会给你的内容foo目录-如果你只有使用(cp/resources "foo")在类路径上的所有这样的目录会被发现,
  • 理论上,类path可能有多个具有相同path文件,这就是为什么该函数返回多个uris ; 在我们的案例中,只有第一个是有趣的。
  • path总是以斜杠开始,所以为了获得相对的path ,我们必须删除它。
  • 也许这对你有帮助。


    我不知道惯用的部分,但资源目录中的文件可以用这种方式列出

    (defn list-resource
      [resource-dir]
      (let [resource (io/file (io/resource resource-dir))]
        (file-seq resource)))
    

    并且将资源中的目录foo中的文件复制到当前路径就像

    (io/copy (io/file (io/resource "foo/test.txt")) (io/file "test.txt"))
    

    结合这两者,你应该能够写出一个递归函数来完成你所要求的


    在尝试了更多并从#clojure获得帮助之后,我从我以前的第一个链接中找到了一种“巧妙的猜测”翻译:

    (ns my-ns
      (:require [me.raynes.fs    :as f])
      (:import [java.util.jar JarFile JarEntry]))
    
    (defn extract-dir-from-jar
      "Takes the string path of a jar, a dir name inside that jar and a destination
      dir, and copies the from dir to the to dir."
      [^String jar-dir from to]
      (let [jar (JarFile. jar-dir)]
        (doseq [^JarEntry file (enumeration-seq (.entries jar))]
          (if (.startsWith (.getName file) from)
            (let [f (f/file to (.getName file))]
              (if (.isDirectory file)
                (f/mkdir f)
                (do (f/mkdirs (f/parent f))
                    (with-open [is (.getInputStream jar file)
                                os (io/output-stream f)]
                      (io/copy is os)))))))))
    

    我想我可以稍微整理一下(特别是围绕.startsWith位),但至少可以完美地工作。

    链接地址: http://www.djcxy.com/p/83879.html

    上一篇: Idiomatic Clojure to copy resources from running jar to outside

    下一篇: UnsatisfiedLinkError (com.esri.core.runtime.LicenseImpl.nativeIsClientIdValid)